#!/bin/bash # Build and upload PPA package with automatic cleanup # Usage: ./ppa-upload.sh [package-name] [ppa-name] [ubuntu-series] [rebuild-number] [--keep-builds] [--rebuild=N] # # Examples: # ./ppa-upload.sh dms # Upload to questing + resolute (default) # ./ppa-upload.sh dms 2 # Native: questing ppa2, resolute ppa3 (auto +1 on second series) # ./ppa-upload.sh dms --rebuild=2 # Rebuild with ppa2 (flag syntax) # ./ppa-upload.sh dms-git # Single package (both series) # ./ppa-upload.sh all # All packages (each to both series) # ./ppa-upload.sh dms resolute # 26.04 LTS only (same as "dms dms resolute") # ./ppa-upload.sh dms questing # 25.10 only # ./ppa-upload.sh dms dms resolute # Explicit PPA name + one series (optional form) # ./ppa-upload.sh dms dms resolute 2 # One series + rebuild number # ./ppa-upload.sh distro/ubuntu/dms dms # Path-style (backward compatible) set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $1"; } success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; } AVAILABLE_PACKAGES=(dms dms-git dms-greeter) KEEP_BUILDS=false REBUILD_RELEASE="" POSITIONAL_ARGS=() for arg in "$@"; do case "$arg" in --keep-builds) KEEP_BUILDS=true ;; --rebuild=*) REBUILD_RELEASE="${arg#*=}" ;; -r|--rebuild) REBUILD_NEXT=true ;; *) if [[ -n "${REBUILD_NEXT:-}" ]]; then REBUILD_RELEASE="$arg" REBUILD_NEXT=false else POSITIONAL_ARGS+=("$arg") fi ;; esac done PACKAGE_INPUT="${POSITIONAL_ARGS[0]:-}" PPA_NAME_INPUT="${POSITIONAL_ARGS[1]:-}" UBUNTU_SERIES_RAW="${POSITIONAL_ARGS[2]:-}" if [[ ${#POSITIONAL_ARGS[@]} -gt 0 ]]; then LAST_INDEX=$((${#POSITIONAL_ARGS[@]} - 1)) LAST_ARG="${POSITIONAL_ARGS[$LAST_INDEX]}" if [[ "$LAST_ARG" =~ ^[0-9]+$ ]] && [[ -z "$REBUILD_RELEASE" ]]; then # Last argument is a number and no --rebuild flag was used # Use it as rebuild release and remove from positional args REBUILD_RELEASE="$LAST_ARG" POSITIONAL_ARGS=("${POSITIONAL_ARGS[@]:0:$LAST_INDEX}") PACKAGE_INPUT="${POSITIONAL_ARGS[0]:-}" PPA_NAME_INPUT="${POSITIONAL_ARGS[1]:-}" UBUNTU_SERIES_RAW="${POSITIONAL_ARGS[2]:-}" fi fi # Shorthand: "dms resolute" / "dms questing" (package + series; PPA inferred — no need for "dms dms resolute") if [[ ${#POSITIONAL_ARGS[@]} -eq 2 ]] && [[ "${POSITIONAL_ARGS[1]}" == "questing" || "${POSITIONAL_ARGS[1]}" == "resolute" ]]; then PACKAGE_INPUT="${POSITIONAL_ARGS[0]}" PPA_NAME_INPUT="" UBUNTU_SERIES_RAW="${POSITIONAL_ARGS[1]}" fi SERIES_LIST=() if [[ -z "$UBUNTU_SERIES_RAW" ]]; then SERIES_LIST=(questing resolute) elif [[ "$UBUNTU_SERIES_RAW" == "questing" || "$UBUNTU_SERIES_RAW" == "resolute" ]]; then SERIES_LIST=("$UBUNTU_SERIES_RAW") else error "Invalid Ubuntu series: $UBUNTU_SERIES_RAW (use questing, resolute, or omit for both)" exit 1 fi SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" BUILD_SCRIPT="$SCRIPT_DIR/ppa-build.sh" if [ ! -f "$BUILD_SCRIPT" ]; then error "Build script not found: $BUILD_SCRIPT" exit 1 fi get_ppa_name() { local pkg="$1" case "$pkg" in dms) echo "dms" ;; dms-git) echo "dms-git" ;; dms-greeter) echo "danklinux" ;; *) echo "" ;; esac } # Support both path-style and name-style arguments PACKAGE_DIR="" PACKAGE_NAME="" PPA_NAME="" if [[ -n "$PACKAGE_INPUT" ]] && [[ "$PACKAGE_INPUT" == *"/"* ]]; then # Path-style argument (backward compatibility) if [[ -d "$PACKAGE_INPUT" ]]; then PACKAGE_DIR="$(cd "$PACKAGE_INPUT" && pwd)" elif [[ -d "$REPO_ROOT/$PACKAGE_INPUT" ]]; then PACKAGE_DIR="$(cd "$REPO_ROOT/$PACKAGE_INPUT" && pwd)" else error "Package directory not found: $PACKAGE_INPUT" exit 1 fi PACKAGE_NAME=$(basename "$PACKAGE_DIR") PPA_NAME="${PPA_NAME_INPUT:-$(get_ppa_name "$PACKAGE_NAME")}" if [[ -z "$PPA_NAME" ]]; then error "Could not determine PPA name for package: $PACKAGE_NAME" error "Please specify PPA name as second argument" exit 1 fi info "Using path-style argument: $PACKAGE_DIR" elif [[ -n "$PACKAGE_INPUT" ]] && [[ "$PACKAGE_INPUT" == "all" ]]; then echo "" info "Building and uploading all packages..." FAILED_PACKAGES=() for pkg in "${AVAILABLE_PACKAGES[@]}"; do echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" info "Processing $pkg..." echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" BUILD_ARGS=("$pkg") [[ -n "$PPA_NAME_INPUT" ]] && BUILD_ARGS+=("$PPA_NAME_INPUT") if [[ ${#SERIES_LIST[@]} -eq 1 ]]; then BUILD_ARGS+=("${SERIES_LIST[0]}") fi [[ -n "$REBUILD_RELEASE" ]] && BUILD_ARGS+=("$REBUILD_RELEASE") [[ "$KEEP_BUILDS" == "true" ]] && BUILD_ARGS+=("--keep-builds") if ! "$0" "${BUILD_ARGS[@]}"; then FAILED_PACKAGES+=("$pkg") error "$pkg failed to upload" fi done echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [[ ${#FAILED_PACKAGES[@]} -eq 0 ]]; then success "All packages uploaded successfully!" else error "Some packages failed: ${FAILED_PACKAGES[*]}" exit 1 fi exit 0 elif [[ -n "$PACKAGE_INPUT" ]]; then VALID_PACKAGE=false for pkg in "${AVAILABLE_PACKAGES[@]}"; do if [[ "$PACKAGE_INPUT" == "$pkg" ]]; then VALID_PACKAGE=true break fi done if [[ "$VALID_PACKAGE" != "true" ]]; then error "Unknown package: $PACKAGE_INPUT" echo "Available packages: ${AVAILABLE_PACKAGES[*]}" exit 1 fi PACKAGE_NAME="$PACKAGE_INPUT" PACKAGE_DIR="$REPO_ROOT/distro/ubuntu/$PACKAGE_NAME" PPA_NAME="${PPA_NAME_INPUT:-$(get_ppa_name "$PACKAGE_NAME")}" else echo "Available packages:" echo "" for i in "${!AVAILABLE_PACKAGES[@]}"; do echo " $((i+1)). ${AVAILABLE_PACKAGES[$i]}" done echo " a. all" echo "" read -rp "Select package (1-${#AVAILABLE_PACKAGES[@]}, a): " selection if [[ "$selection" == "a" ]] || [[ "$selection" == "all" ]]; then PACKAGE_INPUT="all" BUILD_ARGS=("all") [[ -n "$PPA_NAME_INPUT" ]] && BUILD_ARGS+=("$PPA_NAME_INPUT") [[ -n "$REBUILD_RELEASE" ]] && BUILD_ARGS+=("$REBUILD_RELEASE") [[ "$KEEP_BUILDS" == "true" ]] && BUILD_ARGS+=("--keep-builds") exec "$0" "${BUILD_ARGS[@]}" elif [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -le ${#AVAILABLE_PACKAGES[@]} ]]; then PACKAGE_NAME="${AVAILABLE_PACKAGES[$((selection-1))]}" PACKAGE_DIR="$REPO_ROOT/distro/ubuntu/$PACKAGE_NAME" PPA_NAME="${PPA_NAME_INPUT:-$(get_ppa_name "$PACKAGE_NAME")}" else error "Invalid selection" exit 1 fi fi if [ ! -d "$PACKAGE_DIR" ]; then error "Package directory not found: $PACKAGE_DIR" exit 1 fi if [ ! -d "$PACKAGE_DIR/debian" ]; then error "No debian/ directory found in $PACKAGE_DIR" exit 1 fi PACKAGE_DIR=$(cd "$PACKAGE_DIR" && pwd) PARENT_DIR=$(dirname "$PACKAGE_DIR") if [[ ${#SERIES_LIST[@]} -gt 1 ]]; then SOURCE_FORMAT_LINE=$(head -1 "$PACKAGE_DIR/debian/source/format" 2>/dev/null || echo "") IS_NATIVE_DUAL=false if [[ "$SOURCE_FORMAT_LINE" == *"native"* ]]; then IS_NATIVE_DUAL=true info "Native source format: second series uses PPA suffix +1 (or ppa2 if unset) so both uploads succeed." fi export REBUILD_RELEASE for idx in "${!SERIES_LIST[@]}"; do SERIES="${SERIES_LIST[$idx]}" if [[ -n "$PACKAGE_INPUT" ]] && [[ "$PACKAGE_INPUT" == *"/"* ]]; then ARGS=("$PACKAGE_DIR" "$PPA_NAME" "$SERIES") else ARGS=("$PACKAGE_NAME" "$PPA_NAME" "$SERIES") fi if [[ "$IS_NATIVE_DUAL" == true ]]; then if [[ "$idx" -eq 0 ]]; then [[ -n "${REBUILD_RELEASE:-}" ]] && ARGS+=("$REBUILD_RELEASE") else if [[ -n "${REBUILD_RELEASE:-}" ]]; then SECOND_PPA=$((REBUILD_RELEASE + 1)) ARGS+=("$SECOND_PPA") info "Second series ${SERIES}: using ppa${SECOND_PPA} (native dual-series)" else ARGS+=("2") info "Second series ${SERIES}: using ppa2 (native dual-series; first uses default ppa1)" fi fi else [[ -n "${REBUILD_RELEASE:-}" ]] && ARGS+=("$REBUILD_RELEASE") fi [[ "$KEEP_BUILDS" == "true" ]] && ARGS+=("--keep-builds") echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" info "Upload series: $SERIES (of ${SERIES_LIST[*]})" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" "$0" "${ARGS[@]}" || exit 1 done exit 0 fi UBUNTU_SERIES="${SERIES_LIST[0]}" info "Building and uploading: $PACKAGE_NAME" info "Package directory: $PACKAGE_DIR" info "PPA: ppa:avengemedia/$PPA_NAME" info "Ubuntu series: $UBUNTU_SERIES" if [[ -n "$REBUILD_RELEASE" ]]; then info "Rebuild release number: ppa$REBUILD_RELEASE" fi echo info "Step 1: Building source package..." if [[ -n "$REBUILD_RELEASE" ]]; then export REBUILD_RELEASE fi export PPA_UPLOAD_SCRIPT=1 if ! "$BUILD_SCRIPT" "$PACKAGE_DIR" "$UBUNTU_SERIES"; then error "Build failed!" exit 1 fi TEMP_DIR_FILE="$PARENT_DIR/.ppa_build_temp_${PACKAGE_NAME}" if [ -f "$TEMP_DIR_FILE" ]; then BUILD_TEMP_DIR=$(grep -oP 'PPA_BUILD_TEMP_DIR=\K.*' "$TEMP_DIR_FILE") rm -f "$TEMP_DIR_FILE" info "Using build artifacts from temp directory: $BUILD_TEMP_DIR" CHANGES_FILE=$(find "$BUILD_TEMP_DIR" -maxdepth 1 -name "${PACKAGE_NAME}_*_source.changes" -type f 2>/dev/null | sort -V | tail -1) else BUILD_TEMP_DIR="$PARENT_DIR" CHANGES_FILE=$(find "$PARENT_DIR" -maxdepth 1 -name "${PACKAGE_NAME}_*_source.changes" -type f | sort -V | tail -1) fi if [ -z "$CHANGES_FILE" ]; then warn "Changes file not found in $BUILD_TEMP_DIR" warn "Assuming build was skipped (no changes needed) and exiting successfully." exit 0 fi info "Found changes file: $CHANGES_FILE" echo info "Step 2: Uploading to PPA..." if [ "$PPA_NAME" = "danklinux" ] || [ "$PPA_NAME" = "dms" ] || [ "$PPA_NAME" = "dms-git" ]; then warn "Using lftp for upload" BUILD_DIR=$(dirname "$CHANGES_FILE") CHANGES_BASENAME=$(basename "$CHANGES_FILE") DSC_FILE="${CHANGES_BASENAME/_source.changes/.dsc}" TARBALL="${CHANGES_BASENAME/_source.changes/.tar.xz}" BUILDINFO="${CHANGES_BASENAME/_source.changes/_source.buildinfo}" # Check all files exist MISSING_FILES=() [ ! -f "$BUILD_DIR/$DSC_FILE" ] && MISSING_FILES+=("$DSC_FILE") [ ! -f "$BUILD_DIR/$TARBALL" ] && MISSING_FILES+=("$TARBALL") [ ! -f "$BUILD_DIR/$BUILDINFO" ] && MISSING_FILES+=("$BUILDINFO") if [ ${#MISSING_FILES[@]} -gt 0 ]; then error "Missing required files:" for file in "${MISSING_FILES[@]}"; do error " - $file" done exit 1 fi info "Uploading files:" info " - $CHANGES_BASENAME" info " - $DSC_FILE" info " - $TARBALL" info " - $BUILDINFO" echo LFTP_SCRIPT=$(mktemp) cat >"$LFTP_SCRIPT" <