#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' Usage: DEB_SERVER_URL=https://deb.example.com \ DEB_TOKEN=secret \ DEB_REPOSITORY=main \ upload_deb.sh FILE.deb [FILE.deb ...] Options: -s SERVER_URL Override DEB_SERVER_URL -n REPOSITORY Override DEB_REPOSITORY -p UPLOAD_PATH Override DEB_UPLOAD_PATH (default: /api/v2/upload/package) -h Show help The endpoint must accept multipart fields named package, token, and repository_name. Authentication is read only from DEB_TOKEN so it is not exposed in the process command line. EOF } server_url=${DEB_SERVER_URL:-} repository=${DEB_REPOSITORY:-} upload_path=${DEB_UPLOAD_PATH:-/api/v2/upload/package} token=${DEB_TOKEN:-} while getopts ":s:n:p:h" option; do case "$option" in s) server_url=$OPTARG ;; n) repository=$OPTARG ;; p) upload_path=$OPTARG ;; h) usage; exit 0 ;; :) echo "Error: -$OPTARG requires a value" >&2; usage >&2; exit 2 ;; \?) echo "Error: unknown option -$OPTARG" >&2; usage >&2; exit 2 ;; esac done shift $((OPTIND - 1)) if [[ -z "$server_url" || -z "$repository" || -z "$token" || $# -eq 0 ]]; then echo "Error: DEB_SERVER_URL, DEB_TOKEN, DEB_REPOSITORY, and at least one file are required." >&2 usage >&2 exit 2 fi if [[ "$upload_path" != /* ]]; then echo "Error: upload path must start with /" >&2 exit 2 fi if ! command -v curl >/dev/null 2>&1; then echo "Error: curl is required." >&2 exit 2 fi server_url=${server_url%/} success_count=0 fail_count=0 response_file= cleanup() { if [[ -n "$response_file" && -f "$response_file" ]]; then rm -f -- "$response_file" fi } trap cleanup EXIT print_response() { local file=$1 if command -v jq >/dev/null 2>&1 && jq -e . "$file" >/dev/null 2>&1; then jq . "$file" else cat -- "$file" fi } for package_file in "$@"; do if [[ ! -f "$package_file" ]]; then echo "Skip: file not found: $package_file" >&2 fail_count=$((fail_count + 1)) continue fi if [[ "$package_file" != *.deb ]]; then echo "Skip: not a .deb file: $package_file" >&2 fail_count=$((fail_count + 1)) continue fi if [[ ! -s "$package_file" ]]; then echo "Skip: empty file: $package_file" >&2 fail_count=$((fail_count + 1)) continue fi response_file=$(mktemp) echo "Uploading $(basename -- "$package_file") to $server_url (repository $repository)..." http_code=000 if http_code=$(curl --silent --show-error \ --output "$response_file" \ --write-out "%{http_code}" \ --request POST \ "$server_url$upload_path" \ --form "package=@${package_file};type=application/vnd.debian.binary-package" \ --form "token=${token}" \ --form "repository_name=${repository}"); then : else echo "Failed (transport error): $(basename -- "$package_file")" >&2 print_response "$response_file" >&2 fail_count=$((fail_count + 1)) cleanup response_file= continue fi if [[ "$http_code" == 200 || "$http_code" == 201 ]]; then echo "Success ($http_code): $(basename -- "$package_file")" print_response "$response_file" success_count=$((success_count + 1)) else echo "Failed ($http_code): $(basename -- "$package_file")" >&2 print_response "$response_file" >&2 fail_count=$((fail_count + 1)) fi cleanup response_file= done echo "Done. Success: $success_count, Failed: $fail_count" if ((fail_count > 0)); then exit 1 fi