From 7bbb046e8e5a2102e776c256580f931ea6e2ef1a Mon Sep 17 00:00:00 2001 From: forbes Date: Wed, 28 Jan 2026 17:29:09 -0600 Subject: [PATCH] Fix .deb packaging: version must start with digit - Fix version conversion for Debian policy compliance (e.g., weekly-2025.01.28 -> 0~weekly.2025.01.28) - Add MIME type registration for .fcstd files - Add AppStream metainfo for software centers - Add copyright file (required by Debian policy) - Improve maintainer scripts with proper case statements - Expand dependencies in control file (Depends/Recommends/Suggests) - Add .deb build step to release workflow - Simplify build workflow to let script handle version conversion --- .gitea/workflows/build.yml | 7 +- .gitea/workflows/release.yml | 21 +++ package/debian/build-deb.sh | 259 ++++++++++++++++++++++++++++++----- package/debian/control | 18 ++- 4 files changed, 259 insertions(+), 46 deletions(-) diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index b4ec2d81c1..09b9622340 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -141,10 +141,9 @@ jobs: shell: bash run: | # Build .deb package from installed files - VERSION=$(git describe --tags --always) - VERSION="${VERSION#v}" - VERSION="${VERSION//-/.}" - ./package/debian/build-deb.sh build/release/install build/release "$VERSION" + # The build-deb.sh script handles version conversion to Debian format + # (e.g., weekly-2025.01.28 -> 0~weekly.2025.01.28) + ./package/debian/build-deb.sh build/release/install build/release - name: Upload build artifact uses: https://code.forgejo.org/actions/upload-artifact@v3 diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 674933509b..71f1632663 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -91,11 +91,23 @@ jobs: - name: Show ccache statistics run: pixi run ccache -s + - name: Build .deb package + shell: bash + run: | + # Build .deb package from the AppDir used for AppImage + # The build-deb.sh script handles version conversion to Debian format + # (e.g., weekly-2025.01.28 -> 0~weekly.2025.01.28) + ./package/debian/build-deb.sh \ + package/rattler-build/linux/AppDir/usr \ + package/rattler-build/linux \ + "${BUILD_TAG}" + - name: List built artifacts shell: bash run: | echo "Built artifacts:" ls -lah package/rattler-build/linux/*.AppImage* 2>/dev/null || echo "No AppImage files found" + ls -lah package/rattler-build/linux/*.deb* 2>/dev/null || echo "No .deb files found" ls -lah package/rattler-build/linux/*-SHA256.txt 2>/dev/null || echo "No SHA256 files found" - name: Upload AppImage artifact @@ -106,3 +118,12 @@ jobs: package/rattler-build/linux/*.AppImage package/rattler-build/linux/*-SHA256.txt if-no-files-found: error + + - name: Upload .deb artifact + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: kindred-create-deb + path: | + package/rattler-build/linux/*.deb + package/rattler-build/linux/*.deb.sha256 + if-no-files-found: warn diff --git a/package/debian/build-deb.sh b/package/debian/build-deb.sh index dfbde769a6..48106ce49b 100755 --- a/package/debian/build-deb.sh +++ b/package/debian/build-deb.sh @@ -1,6 +1,9 @@ #!/bin/bash # SPDX-License-Identifier: LGPL-2.1-or-later # Build a .deb package from the installed build directory +# +# This script creates a Debian binary package following Debian Policy Manual guidelines. +# See: https://www.debian.org/doc/debian-policy/ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -19,113 +22,293 @@ if [ -z "$INSTALL_DIR" ] || [ -z "$OUTPUT_DIR" ]; then exit 1 fi +# Validate install directory exists +if [ ! -d "$INSTALL_DIR" ]; then + echo "Error: Install directory does not exist: $INSTALL_DIR" + exit 1 +fi + # Get version from git if not provided if [ -z "$VERSION" ]; then VERSION=$(cd "$PROJECT_ROOT" && git describe --tags --always 2>/dev/null || echo "0.1.0") - # Clean up version for debian (replace - with .) - VERSION="${VERSION#v}" # Remove leading 'v' if present - VERSION="${VERSION//-/.}" # Replace - with . fi +# Convert version to Debian-compatible format +# Debian Policy Manual 5.6.12: version must start with a digit +# Format: [epoch:]upstream_version[-debian_revision] +convert_to_debian_version() { + local ver="$1" + + # Remove leading 'v' if present (common in git tags) + ver="${ver#v}" + + # Replace hyphens with dots (hyphens have special meaning in Debian versions) + ver="${ver//-/.}" + + # If version starts with a letter (e.g., 'weekly'), prefix with '0~' + # The ~ character sorts before anything else, ensuring: + # 0~weekly.2025.01.01 < 0.1.0 < 1.0.0 + if [[ "$ver" =~ ^[a-zA-Z] ]]; then + ver="0~${ver}" + fi + + echo "$ver" +} + +VERSION=$(convert_to_debian_version "$VERSION") + PACKAGE_NAME="kindred-create" ARCH="amd64" +# Debian package naming: __.deb DEB_NAME="${PACKAGE_NAME}_${VERSION}_${ARCH}" -echo "Building .deb package: ${DEB_NAME}.deb" -echo " Source: ${INSTALL_DIR}" -echo " Output: ${OUTPUT_DIR}" -echo " Version: ${VERSION}" +echo "========================================" +echo "Building Debian package" +echo "========================================" +echo " Package: ${PACKAGE_NAME}" +echo " Version: ${VERSION}" +echo " Arch: ${ARCH}" +echo " Source: ${INSTALL_DIR}" +echo " Output: ${OUTPUT_DIR}/${DEB_NAME}.deb" +echo "========================================" # Create staging directory STAGING_DIR=$(mktemp -d) trap "rm -rf ${STAGING_DIR}" EXIT -# Create debian package structure +# Create debian package structure following Filesystem Hierarchy Standard mkdir -p "${STAGING_DIR}/DEBIAN" mkdir -p "${STAGING_DIR}/opt/${PACKAGE_NAME}" mkdir -p "${STAGING_DIR}/usr/bin" mkdir -p "${STAGING_DIR}/usr/share/applications" mkdir -p "${STAGING_DIR}/usr/share/icons/hicolor/scalable/apps" +mkdir -p "${STAGING_DIR}/usr/share/icons/hicolor/48x48/apps" +mkdir -p "${STAGING_DIR}/usr/share/icons/hicolor/256x256/apps" mkdir -p "${STAGING_DIR}/usr/share/mime/packages" +mkdir -p "${STAGING_DIR}/usr/share/metainfo" +mkdir -p "${STAGING_DIR}/usr/share/doc/${PACKAGE_NAME}" # Copy installed files echo "Copying installed files..." cp -a "${INSTALL_DIR}"/* "${STAGING_DIR}/opt/${PACKAGE_NAME}/" -# Create symlinks in /usr/bin +# Create symlinks in /usr/bin for system-wide access ln -sf "/opt/${PACKAGE_NAME}/bin/FreeCAD" "${STAGING_DIR}/usr/bin/kindred-create" ln -sf "/opt/${PACKAGE_NAME}/bin/FreeCADCmd" "${STAGING_DIR}/usr/bin/kindred-create-cmd" -# Create desktop entry +# Create desktop entry following freedesktop.org specification cat > "${STAGING_DIR}/usr/share/applications/kindred-create.desktop" << 'EOF' [Desktop Entry] +Version=1.1 +Type=Application Name=Kindred Create +GenericName=CAD Application Comment=Engineering-focused parametric 3D CAD platform -Exec=/opt/kindred-create/bin/FreeCAD %F +Exec=kindred-create %F Icon=kindred-create Terminal=false -Type=Application Categories=Graphics;Science;Engineering; -MimeType=application/x-extension-fcstd; +MimeType=application/x-extension-fcstd;application/x-freecad; +Keywords=CAD;3D;modeling;engineering;design;parametric;FreeCAD; +StartupNotify=true StartupWMClass=FreeCAD EOF -# Copy icon if available, otherwise create a placeholder reference +# Copy or create icon files if [ -f "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/org.freecad.FreeCAD.svg" ]; then cp "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/org.freecad.FreeCAD.svg" \ "${STAGING_DIR}/usr/share/icons/hicolor/scalable/apps/kindred-create.svg" -elif [ -f "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/freecad.svg" ]; then - cp "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/freecad.svg" \ +elif [ -f "${PROJECT_ROOT}/resources/branding/kindred-create.svg" ]; then + cp "${PROJECT_ROOT}/resources/branding/kindred-create.svg" \ "${STAGING_DIR}/usr/share/icons/hicolor/scalable/apps/kindred-create.svg" fi +# Copy PNG icons if available +for size in 48 256; do + if [ -f "${INSTALL_DIR}/share/icons/hicolor/${size}x${size}/apps/org.freecad.FreeCAD.png" ]; then + cp "${INSTALL_DIR}/share/icons/hicolor/${size}x${size}/apps/org.freecad.FreeCAD.png" \ + "${STAGING_DIR}/usr/share/icons/hicolor/${size}x${size}/apps/kindred-create.png" + fi +done + +# Create MIME type definition for .fcstd files +cat > "${STAGING_DIR}/usr/share/mime/packages/kindred-create.xml" << 'EOF' + + + + FreeCAD Document + + + + + +EOF + +# Create AppStream metainfo for software centers +cat > "${STAGING_DIR}/usr/share/metainfo/kindred-create.metainfo.xml" << EOF + + + kindred-create + Kindred Create + Engineering-focused parametric 3D CAD platform + CC0-1.0 + LGPL-2.1-or-later + +

+ Kindred Create is an engineering-focused parametric 3D CAD platform + built on FreeCAD 1.0+. It provides a streamlined interface for + mechanical engineering and product design. +

+

Features include:

+
    +
  • Parametric modeling with constraint-based sketcher
  • +
  • Part Design workbench for solid modeling
  • +
  • Assembly workbench for multi-part designs
  • +
  • TechDraw workbench for 2D technical drawings
  • +
  • FEM workbench for finite element analysis
  • +
  • CAM workbench for CNC machining
  • +
+
+ kindred-create.desktop + https://gitea.kindred.internal/kindred/create + https://gitea.kindred.internal/kindred/create/issues + + kindred-create + kindred-create-cmd + + + + + +
+EOF + +# Create basic copyright file (required by Debian policy) +cat > "${STAGING_DIR}/usr/share/doc/${PACKAGE_NAME}/copyright" << 'EOF' +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Kindred Create +Upstream-Contact: Kindred Team +Source: https://gitea.kindred.internal/kindred/create + +Files: * +Copyright: 2024-2026 Kindred + 2001-2024 FreeCAD Contributors +License: LGPL-2.1-or-later + +License: LGPL-2.1-or-later + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + . + On Debian systems, the complete text of the GNU Lesser General Public + License can be found in `/usr/share/common-licenses/LGPL-2.1'. +EOF + # Generate control file with actual version sed "s/\${VERSION}/${VERSION}/" "${SCRIPT_DIR}/control" > "${STAGING_DIR}/DEBIAN/control" -# Calculate installed size (in KB) +# Calculate and append installed size (in KiB, as required by Debian policy) INSTALLED_SIZE=$(du -sk "${STAGING_DIR}" | cut -f1) echo "Installed-Size: ${INSTALLED_SIZE}" >> "${STAGING_DIR}/DEBIAN/control" -# Create postinst script for updating desktop database +# Create postinst script for post-installation setup cat > "${STAGING_DIR}/DEBIAN/postinst" << 'EOF' -#!/bin/bash +#!/bin/sh set -e -if [ -x /usr/bin/update-desktop-database ]; then - /usr/bin/update-desktop-database -q /usr/share/applications || true -fi -if [ -x /usr/bin/gtk-update-icon-cache ]; then - /usr/bin/gtk-update-icon-cache -q /usr/share/icons/hicolor || true -fi + +case "$1" in + configure) + # Update desktop database + if command -v update-desktop-database > /dev/null 2>&1; then + update-desktop-database -q /usr/share/applications 2>/dev/null || true + fi + + # Update icon cache + if command -v gtk-update-icon-cache > /dev/null 2>&1; then + gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor 2>/dev/null || true + fi + + # Update MIME database + if command -v update-mime-database > /dev/null 2>&1; then + update-mime-database /usr/share/mime 2>/dev/null || true + fi + ;; +esac + +exit 0 EOF chmod 755 "${STAGING_DIR}/DEBIAN/postinst" -# Create postrm script +# Create postrm script for post-removal cleanup cat > "${STAGING_DIR}/DEBIAN/postrm" << 'EOF' -#!/bin/bash +#!/bin/sh set -e -if [ -x /usr/bin/update-desktop-database ]; then - /usr/bin/update-desktop-database -q /usr/share/applications || true -fi -if [ -x /usr/bin/gtk-update-icon-cache ]; then - /usr/bin/gtk-update-icon-cache -q /usr/share/icons/hicolor || true -fi + +case "$1" in + remove|purge) + # Update desktop database + if command -v update-desktop-database > /dev/null 2>&1; then + update-desktop-database -q /usr/share/applications 2>/dev/null || true + fi + + # Update icon cache + if command -v gtk-update-icon-cache > /dev/null 2>&1; then + gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor 2>/dev/null || true + fi + + # Update MIME database + if command -v update-mime-database > /dev/null 2>&1; then + update-mime-database /usr/share/mime 2>/dev/null || true + fi + ;; +esac + +exit 0 EOF chmod 755 "${STAGING_DIR}/DEBIAN/postrm" -# Set proper permissions +# Set proper permissions following Debian policy +# Directories: 755, Files: 644, Executables: 755 +echo "Setting file permissions..." find "${STAGING_DIR}" -type d -exec chmod 755 {} \; find "${STAGING_DIR}/opt" -type f -exec chmod 644 {} \; -find "${STAGING_DIR}/opt/${PACKAGE_NAME}/bin" -type f -exec chmod 755 {} \; + +# Make binaries executable +if [ -d "${STAGING_DIR}/opt/${PACKAGE_NAME}/bin" ]; then + find "${STAGING_DIR}/opt/${PACKAGE_NAME}/bin" -type f -exec chmod 755 {} \; +fi + +# Make shared libraries executable (required for proper loading) +find "${STAGING_DIR}/opt/${PACKAGE_NAME}" -name "*.so" -type f -exec chmod 755 {} \; +find "${STAGING_DIR}/opt/${PACKAGE_NAME}" -name "*.so.*" -type f -exec chmod 755 {} \; + +# Ensure DEBIAN scripts have correct permissions (must be 0555 to 0775) chmod 755 "${STAGING_DIR}/DEBIAN/postinst" chmod 755 "${STAGING_DIR}/DEBIAN/postrm" # Build the .deb package +# --root-owner-group ensures all files are owned by root:root (standard practice) mkdir -p "${OUTPUT_DIR}" +echo "Building package..." dpkg-deb --build --root-owner-group "${STAGING_DIR}" "${OUTPUT_DIR}/${DEB_NAME}.deb" -# Generate checksum +# Verify the package +echo "Verifying package..." +dpkg-deb --info "${OUTPUT_DIR}/${DEB_NAME}.deb" + +# Generate checksums cd "${OUTPUT_DIR}" sha256sum "${DEB_NAME}.deb" > "${DEB_NAME}.deb.sha256" -echo "Package created: ${OUTPUT_DIR}/${DEB_NAME}.deb" -ls -lh "${OUTPUT_DIR}/${DEB_NAME}.deb" +echo "" +echo "========================================" +echo "Package built successfully!" +echo "========================================" +echo " File: ${OUTPUT_DIR}/${DEB_NAME}.deb" +echo " Size: $(ls -lh "${DEB_NAME}.deb" | awk '{print $5}')" +echo " SHA256: $(cat "${DEB_NAME}.deb.sha256" | cut -d' ' -f1)" +echo "========================================" +echo "" +echo "Install with: sudo dpkg -i ${DEB_NAME}.deb" +echo " sudo apt-get install -f # to resolve dependencies" diff --git a/package/debian/control b/package/debian/control index 6bde8752a4..b382f34039 100644 --- a/package/debian/control +++ b/package/debian/control @@ -4,10 +4,20 @@ Section: science Priority: optional Architecture: amd64 Maintainer: Kindred Team +Homepage: https://gitea.kindred.internal/kindred/create Description: Engineering-focused parametric 3D CAD platform Kindred Create is an engineering-focused parametric 3D CAD platform built on FreeCAD 1.0+. It provides a streamlined interface for - mechanical engineering and product design with integrated workbenches - for Part Design, Assembly, and Sketcher tools. -Depends: libc6 (>= 2.31), libstdc++6 (>= 10), libgl1, libx11-6, libxcb1 -Homepage: https://gitea.kindred.internal/kindred/create + mechanical engineering and product design. + . + Features include: + * Parametric modeling with constraint-based sketcher + * Part Design workbench for solid modeling + * Assembly workbench for multi-part designs + * TechDraw workbench for 2D technical drawings + * FEM workbench for finite element analysis + * CAM workbench for CNC machining + * Import/export of STEP, IGES, STL, and other formats +Depends: libc6 (>= 2.31), libstdc++6 (>= 10), libgl1, libglu1-mesa, libx11-6, libxcb1, libxext6, libxi6, libxmu6, libxrender1, libfreetype6, libfontconfig1, python3 (>= 3.10), python3-numpy, python3-pyside6.qtcore, python3-pyside6.qtgui, python3-pyside6.qtwidgets, python3-pyside6.qtsvg +Recommends: python3-matplotlib, python3-pivy, calculix-ccx, gmsh, graphviz, python3-collada, python3-defusedxml, python3-yaml +Suggests: openscad, povray, python3-ifcopenshell