Push code

This commit is contained in:
2026-01-28 23:03:50 +01:00
parent 5bd203b516
commit 00bbd6534b
19 changed files with 1224 additions and 0 deletions

152
scripts/build-deb.sh Executable file
View File

@@ -0,0 +1,152 @@
#!/bin/bash
# build-deb.sh - Build Debian package for FeatherDDNS (runs inside container)
set -e
VERSION="${VERSION:-1.0.0}"
ARCH="amd64"
PACKAGE_NAME="featherddns"
MAINTAINER="Steven Tracey <steven@nevets.tech>"
HOMEPAGE="https://git.nevets.tech/Steven/FeatherDDNS"
BUILD_DIR="build/${PACKAGE_NAME}_${VERSION}_${ARCH}"
echo "Building ${PACKAGE_NAME} version ${VERSION}..."
# Clean and create build directory
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR/DEBIAN"
mkdir -p "$BUILD_DIR/usr/bin"
mkdir -p "$BUILD_DIR/etc/featherddns"
mkdir -p "$BUILD_DIR/lib/systemd/system"
# Copy and strip binary
echo "Copying binary..."
cp "bin/FeatherDDNS" "$BUILD_DIR/usr/bin/featherddns"
strip "$BUILD_DIR/usr/bin/featherddns"
chmod 755 "$BUILD_DIR/usr/bin/featherddns"
# Copy config if exists
if [ -f "config.json.example" ]; then
echo "Copying configuration..."
cp "config.json.example" "$BUILD_DIR/etc/featherddns/config.json"
chmod 644 "$BUILD_DIR/etc/featherddns/config.json"
fi
# Copy systemd service if exists
if [ -f "featherddns.service" ]; then
echo "Copying systemd service..."
cp "featherddns.service" "$BUILD_DIR/lib/systemd/system/"
chmod 644 "$BUILD_DIR/lib/systemd/system/featherddns.service"
fi
# Create control file
cat > "$BUILD_DIR/DEBIAN/control" <<EOF
Package: ${PACKAGE_NAME}
Version: ${VERSION}
Section: net
Priority: optional
Architecture: ${ARCH}
Maintainer: ${MAINTAINER}
Depends: libc6
Homepage: ${HOMEPAGE}
Description: FeatherDDNS - Lightweight Dynamic DNS Server
A lightweight dynamic DNS server for updating DNS records
via HTTP API requests.
EOF
# Create conffiles if config exists
if [ -f "$BUILD_DIR/etc/featherddns/config.json" ]; then
cat > "$BUILD_DIR/DEBIAN/conffiles" <<EOF
/etc/featherddns/config.json
EOF
chmod 644 "$BUILD_DIR/DEBIAN/conffiles"
fi
# Create postinst script
cat > "$BUILD_DIR/DEBIAN/postinst" <<'EOF'
#!/bin/bash
set -e
case "$1" in
configure)
# Create featherddns user if it doesn't exist
if ! getent passwd featherddns > /dev/null; then
useradd --system --home-dir /var/lib/featherddns --shell /bin/false featherddns
fi
# Create directories
mkdir -p /var/lib/featherddns
mkdir -p /var/log/featherddns
chown featherddns:featherddns /var/lib/featherddns
chown featherddns:featherddns /var/log/featherddns
# Reload systemd
if [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null || true
fi
;;
esac
exit 0
EOF
chmod 755 "$BUILD_DIR/DEBIAN/postinst"
# Create prerm script
cat > "$BUILD_DIR/DEBIAN/prerm" <<'EOF'
#!/bin/bash
set -e
case "$1" in
remove|upgrade)
if [ -d /run/systemd/system ]; then
systemctl stop featherddns.service >/dev/null 2>&1 || true
fi
;;
esac
exit 0
EOF
chmod 755 "$BUILD_DIR/DEBIAN/prerm"
# Create postrm script
cat > "$BUILD_DIR/DEBIAN/postrm" <<'EOF'
#!/bin/bash
set -e
case "$1" in
remove)
if [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null || true
fi
;;
purge)
rm -rf /etc/featherddns
rm -rf /var/lib/featherddns
rm -rf /var/log/featherddns
if [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null || true
fi
;;
esac
exit 0
EOF
chmod 755 "$BUILD_DIR/DEBIAN/postrm"
# Build the package
echo "Building package..."
dpkg-deb --build --root-owner-group "$BUILD_DIR"
# Move to dist directory
mkdir -p dist
mv "${BUILD_DIR}.deb" "dist/"
echo "Package built: dist/${PACKAGE_NAME}_${VERSION}_${ARCH}.deb"
# Run lintian check
if command -v lintian > /dev/null 2>&1; then
echo "Running lintian check..."
lintian "dist/${PACKAGE_NAME}_${VERSION}_${ARCH}.deb" || true
fi
echo "Done!"

116
scripts/package.sh Executable file
View File

@@ -0,0 +1,116 @@
#!/bin/bash
# package.sh - Build Debian package for FeatherDDNS using a Debian container
#
# Usage: ./scripts/package.sh [version]
#
# Environment Variables:
# CONTAINER_RUNTIME Container runtime to use (default: podman)
# VERSION Override package version
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
IMAGE_NAME="featherddns-debian-builder"
CONTAINER_RUNTIME="${CONTAINER_RUNTIME:-podman}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
# Get version from Makefile or argument
get_version() {
grep "^VERSION" "$PROJECT_ROOT/Makefile" 2>/dev/null | head -1 | sed 's/.*:= *//' | tr -d ' '
}
VERSION="${1:-${VERSION:-$(get_version)}}"
VERSION="${VERSION:-1.0.0}"
info "Packaging FeatherDDNS version ${VERSION}"
# Check container runtime
if ! command -v "$CONTAINER_RUNTIME" >/dev/null 2>&1; then
error "Container runtime '$CONTAINER_RUNTIME' not found"
info "Install podman or docker, or set CONTAINER_RUNTIME"
exit 1
fi
info "Using container runtime: $CONTAINER_RUNTIME"
# Check binary exists
if [[ ! -f "$PROJECT_ROOT/bin/FeatherDDNS" ]]; then
error "Binary not found: bin/FeatherDDNS"
info "Build first with: make build"
exit 1
fi
success "Binary found: bin/FeatherDDNS"
# Build container image if needed
info "Checking for debian-builder image..."
NEED_BUILD=false
if ! $CONTAINER_RUNTIME image exists "$IMAGE_NAME" 2>/dev/null; then
info "Image does not exist, building..."
NEED_BUILD=true
else
DOCKERFILE_TIME=$(stat -c %Y "$PROJECT_ROOT/Dockerfile.debian-builder" 2>/dev/null || echo 0)
IMAGE_TIME=$($CONTAINER_RUNTIME image inspect "$IMAGE_NAME" --format '{{.Created}}' 2>/dev/null | xargs -I{} date -d {} +%s 2>/dev/null || echo 0)
if [[ "$DOCKERFILE_TIME" -gt "$IMAGE_TIME" ]]; then
info "Dockerfile is newer than image, rebuilding..."
NEED_BUILD=true
fi
fi
if [[ "$NEED_BUILD" == "true" ]]; then
if ! $CONTAINER_RUNTIME build -t "$IMAGE_NAME" -f "$PROJECT_ROOT/Dockerfile.debian-builder" "$PROJECT_ROOT"; then
error "Failed to build debian-builder image"
exit 1
fi
success "debian-builder image built"
else
success "debian-builder image is up-to-date"
fi
# Create dist directory
mkdir -p "$PROJECT_ROOT/dist"
# Determine SELinux mount option
MOUNT_OPT=""
if command -v getenforce >/dev/null 2>&1 && [[ "$(getenforce 2>/dev/null)" != "Disabled" ]]; then
MOUNT_OPT=":Z"
info "SELinux detected, using :Z mount flag"
fi
# Run packaging in container
info "Running packaging in container..."
if ! $CONTAINER_RUNTIME run --rm \
-v "${PROJECT_ROOT}:/build${MOUNT_OPT}" \
-e "VERSION=${VERSION}" \
-w /build \
"$IMAGE_NAME" \
/bin/bash -c "./scripts/build-deb.sh"; then
error "Container packaging failed"
exit 1
fi
# Verify output
DEB_FILE=$(find "$PROJECT_ROOT/dist" -name "featherddns_*.deb" -type f 2>/dev/null | head -1)
if [[ -n "$DEB_FILE" ]]; then
success "Package created: $DEB_FILE"
ls -lh "$DEB_FILE"
else
error "Package not found in dist/"
ls -la "$PROJECT_ROOT/dist/" 2>/dev/null || true
exit 1
fi
success "Packaging complete!"

150
scripts/publish-to-gitea.sh Executable file
View File

@@ -0,0 +1,150 @@
#!/bin/bash
# Upload Debian packages to Gitea APT registry
set -e
GITEA_URL="${GITEA_URL:-https://git.nevets.tech}"
GITEA_OWNER="${GITEA_OWNER:-steven}"
GITEA_TOKEN="${GITEA_TOKEN}"
DIST_DIR="${DIST_DIR:-dist}"
DISTRIBUTION="${DISTRIBUTION:-trixie}" # Debian 13
COMPONENT="${COMPONENT:-main}"
PACKAGE_FILTER="${PACKAGE_FILTER:-}" # Optional filter for specific package
# Colors for output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # No Color
if [ -z "$GITEA_TOKEN" ]; then
echo -e "${RED}Error: GITEA_TOKEN environment variable not set${NC}"
echo "Set it with: export GITEA_TOKEN='your-token-here'"
echo ""
echo "The token must have the following permissions:"
echo " - write:package (to upload packages)"
echo " - read:package (to read package metadata)"
echo ""
echo "Create a token at: ${GITEA_URL}/user/settings/applications"
exit 1
fi
if [ ! -d "$DIST_DIR" ]; then
echo -e "${RED}Error: Distribution directory $DIST_DIR not found${NC}"
echo "Build packages first with: make package"
exit 1
fi
echo -e "${BLUE}Publishing packages to Gitea APT registry...${NC}"
echo "Repository: ${GITEA_URL}/api/packages/${GITEA_OWNER}/debian"
echo "Distribution: ${DISTRIBUTION}"
echo "Component: ${COMPONENT}"
if [ -n "$PACKAGE_FILTER" ]; then
echo "Filter: ${PACKAGE_FILTER}"
fi
echo ""
# Verify token has package access
echo -e "${BLUE}Verifying token permissions...${NC}"
VERIFY_CODE=$(curl -s -w "%{http_code}" -o /tmp/gitea_verify.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
"${GITEA_URL}/api/v1/user")
if [ "$VERIFY_CODE" -eq 200 ]; then
USER=$(grep -o '"login":"[^"]*"' /tmp/gitea_verify.txt | cut -d'"' -f4)
echo -e "${GREEN}✓ Token authenticated as user: ${USER}${NC}"
else
echo -e "${RED}✗ Token verification failed (HTTP ${VERIFY_CODE})${NC}"
cat /tmp/gitea_verify.txt
echo ""
echo "Please check your GITEA_TOKEN and try again."
exit 1
fi
rm -f /tmp/gitea_verify.txt
echo ""
SUCCESS_COUNT=0
FAIL_COUNT=0
for deb in "$DIST_DIR"/*.deb; do
if [ -f "$deb" ]; then
PACKAGE_NAME=$(basename "$deb")
# Skip if filter is set and package doesn't match
if [ -n "$PACKAGE_FILTER" ]; then
if [[ ! "$PACKAGE_NAME" =~ ^${PACKAGE_FILTER}_ ]]; then
echo -e "${BLUE}Skipping ${PACKAGE_NAME} (doesn't match filter)${NC}"
continue
fi
fi
echo -e "${BLUE}Uploading ${PACKAGE_NAME}...${NC}"
# Try uploading with token authentication
HTTP_CODE=$(curl -X PUT \
-w "%{http_code}" \
-o /tmp/gitea_upload_response.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"${deb}" \
"${GITEA_URL}/api/packages/${GITEA_OWNER}/debian/pool/${DISTRIBUTION}/${COMPONENT}/upload")
if [ "$HTTP_CODE" -eq 201 ] || [ "$HTTP_CODE" -eq 200 ]; then
echo -e "${GREEN}✓ Uploaded ${PACKAGE_NAME}${NC}"
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
else
echo -e "${RED}✗ Failed to upload ${PACKAGE_NAME} (HTTP ${HTTP_CODE})${NC}"
echo "Response:"
cat /tmp/gitea_upload_response.txt
echo ""
# Provide troubleshooting guidance for common errors
if [ "$HTTP_CODE" -eq 401 ]; then
echo -e "${RED}Authentication failed. Please check:${NC}"
echo " 1. Token is valid and not expired"
echo " 2. Token has 'write:package' permission"
echo " 3. You have access to the '${GITEA_OWNER}' organization"
echo " Create/update token at: ${GITEA_URL}/user/settings/applications"
elif [ "$HTTP_CODE" -eq 403 ]; then
echo -e "${RED}Permission denied. Ensure the token has package write access.${NC}"
elif [ "$HTTP_CODE" -eq 404 ]; then
echo -e "${RED}Repository not found. Verify the owner '${GITEA_OWNER}' exists.${NC}"
fi
echo ""
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
fi
done
echo ""
echo -e "${BLUE}Upload Summary:${NC}"
echo -e "${GREEN}Successful: ${SUCCESS_COUNT}${NC}"
if [ "$FAIL_COUNT" -gt 0 ]; then
echo -e "${RED}Failed: ${FAIL_COUNT}${NC}"
fi
echo ""
if [ "$SUCCESS_COUNT" -gt 0 ]; then
echo -e "${GREEN}Repository setup instructions:${NC}"
echo ""
echo " # Add GPG key"
echo " sudo curl ${GITEA_URL}/api/packages/${GITEA_OWNER}/debian/repository.key -o /etc/apt/keyrings/gitea-${GITEA_OWNER}.asc"
echo ""
echo " # Add repository"
echo " echo \"deb [signed-by=/etc/apt/keyrings/gitea-${GITEA_OWNER}.asc] ${GITEA_URL}/api/packages/${GITEA_OWNER}/debian ${DISTRIBUTION} ${COMPONENT}\" | sudo tee -a /etc/apt/sources.list.d/gitea-${GITEA_OWNER}.list"
echo ""
echo " # Update package list"
echo " sudo apt update"
echo ""
echo " # Install packages"
echo " sudo apt install featherddns"
echo ""
fi
# Cleanup
rm -f /tmp/gitea_upload_response.txt
if [ "$FAIL_COUNT" -gt 0 ]; then
exit 1
fi
exit 0