Skip to content

Conversation

Copy link

Copilot AI commented Sep 12, 2025

This PR adds comprehensive Flatpak packaging support for UltiMaker Cura, providing Linux users with a modern universal package format option alongside the existing AppImage packages.

What's Added

The new /packaging/Flatpak/ directory contains a complete Flatpak build system that follows the same workflow as the existing AppImage configuration:

Core Files

  • com.ultimaker.cura.json - Flatpak manifest using KDE Platform runtime with Qt6 support
  • cura.desktop - Desktop integration file adapted from AppImage version
  • cura.appdata.xml - Enhanced AppStream metadata for software centers

Build Infrastructure

  • build.sh - Automated build script with Conan + PyInstaller + Flatpak workflow
  • README.md - Comprehensive documentation covering prerequisites, build process, and usage
  • LIMITATIONS.md - Documents current limitations and future improvement paths

Key Features

Universal Linux Support: Flatpak packages run on any Linux distribution with Flatpak support, providing consistent behavior across different systems.

Proper Sandboxing: The package includes carefully configured permissions for filesystem access, graphics acceleration, and desktop integration while maintaining security.

Consistent Build Process: Uses the same Conan + PyInstaller workflow as AppImage packaging for maximum compatibility and reliability.

Desktop Integration: Full integration with application menus, file associations for 3D model formats, and AppStream metadata for software centers.

Technical Approach

The Flatpak implementation follows the proven AppImage build workflow:

  1. Conan Dependencies: Uses conan install --requires "cura/..." --build=missing to install and build all dependencies
  2. PyInstaller Distribution: Creates a self-contained application bundle using PyInstaller
  3. Flatpak Packaging: Packages the PyInstaller output into a Flatpak with proper sandboxing

This approach ensures:

  • Same dependency management as other Cura packages
  • Full feature parity including CuraEngine and native libraries
  • Integration with existing CI/CD infrastructure
  • Consistent behavior across packaging formats

Compatibility

This implementation maintains full compatibility with existing packaging:

  • Uses the same application ID (com.ultimaker.cura)
  • Shares desktop and AppData files with minor Flatpak-specific adaptations
  • Utilizes the same icon resources at multiple resolutions
  • Preserves all MIME type associations
  • Supports the same build configuration options (Enterprise, Staging, etc.)

Usage

Users can build the Flatpak using the provided automation:

cd packaging/Flatpak
./build.sh all  # Setup, build Conan + PyInstaller, package Flatpak, and install
./build.sh run  # Launch the application

The build script supports environment variables for customization:

export CURA_CONAN_VERSION="cura/5.6.0@ultimaker/stable"
export ENTERPRISE=true
./build.sh build

Future Work

This implementation provides a solid foundation with the same proven build process as AppImage. Future improvements can focus on:

  • CI/CD integration for automated builds
  • Distribution through Flathub
  • Size optimization and performance tuning
  • Extensive testing across different Linux distributions

This PR establishes Flatpak support using the established build infrastructure and can be iteratively improved based on community feedback and testing.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI changed the title [WIP] Create a Flatpak package for Cura, look at the AppImage-builder and the AppImage for inspiration Add Flatpak packaging support for UltiMaker Cura Sep 12, 2025
Copilot AI requested a review from jellespijker September 12, 2025 11:38
Copilot finished work on behalf of jellespijker September 12, 2025 11:38
@jellespijker
Copy link
Member

@copilot the AppImage is build by the GitHub CI from this workflow: https://github.com/Ultimaker/cura-workflows/blob/main/.github/workflows/cura-installer-linux.yml

The Flatpak should be build similarly, by first installing and building all dependencies with Conan, then using PyInstaller to create the App, which is then packaged.

name: Linux Installer
run-name: ${{ inputs.cura_conan_version }} for Linux-X64 by @${{ github.actor }}

on:
  workflow_call:
    inputs:
      cura_conan_version:
        description: 'Cura Conan Version'
        default: ''
        required: false
        type: string

      package_overrides:
        description: 'List of specific packages to be used (space-separated)'
        default: ''
        required: false
        type: string

      conan_args:
        description: 'Conan args'
        default: ''
        required: false
        type: string

      enterprise:
        description: 'Build Cura as an Enterprise edition'
        default: false
        required: true
        type: boolean

      staging:
        description: 'Use staging API'
        default: false
        required: true
        type: boolean

      operating_system:
        description: 'OS'
        required: true
        default: 'ubuntu-22.04'
        type: string

      private_data:
        required: false
        default: false
        type: boolean

permissions:
  contents: read

jobs:
  cura-installer-create:
    name: Build linux AppImage
    runs-on: ${{ inputs.operating_system }}

    steps:
      - name: Setup the build environment
        id: setup-environment
        uses: ultimaker/cura-workflows/.github/actions/setup-build-environment@main
        with:
          conan_user: ${{ secrets.CONAN_USER }}
          conan_password: ${{ secrets.CONAN_PASS }}
          private_data: ${{ inputs.private_data }}
          install_system_dependencies: true
          repository_path: _cura_sources # we don't want the actual sources to interfere with the built conan package

      - name: Set packages overrides
        id: set-overrides
        uses: ultimaker/cura-workflows/.github/actions/set-package-overrides@main
        with:
          package_overrides: ${{ inputs.package_overrides }}
          profile: installer.jinja

      - name: Install AppImage builder
        run: |
          chmod +x ./Cura-workflows/runner_scripts/appimage_setup.sh
          ./Cura-workflows/runner_scripts/appimage_setup.sh

      - name: Configure GPG Key
        run: echo -n "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --import

      - name: Gather/build the packages
        run: conan install --requires "${{ inputs.cura_conan_version != '' && inputs.cura_conan_version || format('cura/{0}@ultimaker/testing', steps.setup-environment.outputs.package_version) }}" ${{ inputs.conan_args }} --build=missing --update -of cura_inst --deployer-package="*" --profile ${{ steps.set-overrides.outputs.profile }} -c user.sentry:token="${{ secrets.CURAENGINE_SENTRY_TOKEN }}" ${{ inputs.enterprise && '-o "cura/*:enterprise=True"' || '' }} ${{ inputs.staging && '-o "cura/*:staging=True"' || '' }} ${{ inputs.private_data && '-o "cura/*:internal=True"' || '' }}

      - name: Create the Cura distribution with pyinstaller
        id: prepare-distribution
        run: |
          source cura_inst/conanrun.sh
          python -m venv cura_installer_venv
          source cura_installer_venv/bin/activate
          ls cura_inst/packaging/pip_requirements_{core,installer}_*.txt | xargs -I {} pip install -r {}

          python Cura-workflows/runner_scripts/prepare_installer.py --os ${{ runner.os }} --architecture X64 ${{ inputs.enterprise && '--enterprise' || '' }} ${{ inputs.private_data && '--internal' || '' }} --summary-output "$GITHUB_STEP_SUMMARY" --variables-output "$GITHUB_OUTPUT"

          pyinstaller ./cura_inst/UltiMaker-Cura.spec

      - name: Create the Linux AppImage (Bash)
        run: |
          python ../cura_inst/packaging/AppImage-builder/create_appimage.py ./UltiMaker-Cura "${{ steps.prepare-distribution.outputs.CURA_VERSION_FULL }}" "${{ steps.prepare-distribution.outputs.INSTALLER_FILENAME }}.AppImage"
          chmod +x "${{ steps.prepare-distribution.outputs.INSTALLER_FILENAME }}.AppImage"
        working-directory: dist

      - name: Upload the AppImage
        uses: actions/upload-artifact@v4
        with:
          name: ${{ steps.prepare-distribution.outputs.INSTALLER_FILENAME }}-AppImage
          path: dist/${{ steps.prepare-distribution.outputs.INSTALLER_FILENAME }}.AppImage
          retention-days: 5

      - name: Upload the asc
        uses: actions/upload-artifact@v4
        with:
          name: ${{ steps.prepare-distribution.outputs.INSTALLER_FILENAME }}-asc
          path: dist/${{ steps.prepare-distribution.outputs.INSTALLER_FILENAME }}.AppImage.asc
          retention-days: 5

      - name: Upload the built Package(s)
        if: ${{ always() }}
        uses: ultimaker/cura-workflows/.github/actions/upload-conan-package@main
        continue-on-error: true

      - name: Clean local cache
        if: ${{ always() && startsWith(inputs.operating_system, 'self-hosted') }}
        run: conan remove '*' --lru=1w -c

Copy link
Author

Copilot AI commented Sep 12, 2025

@copilot the AppImage is build by the GitHub CI from this workflow: https://github.com/Ultimaker/cura-workflows/blob/main/.github/workflows/cura-installer-linux.yml

The Flatpak should be build sim...

You're absolutely right. I've updated the Flatpak implementation to follow the same build workflow as the AppImage:

  1. Conan Dependencies: Now uses conan install --requires "cura/..." --build=missing to install and build all dependencies
  2. PyInstaller Distribution: Creates the app using PyInstaller with the same process as AppImage
  3. Flatpak Packaging: Packages the PyInstaller output into a Flatpak

The key changes in commit cf348c3:

  • Updated Flatpak manifest to expect PyInstaller distribution as input
  • Modified build script to use Conan + PyInstaller workflow before Flatpak packaging
  • Removed custom Python dependency installation in favor of Conan's dependency chain
  • Added support for the same environment variables (ENTERPRISE, STAGING, etc.)

This ensures consistency with the existing build infrastructure and uses the proven dependency management approach. The Flatpak now serves as just the final packaging step, similar to how AppImage works.

Copilot finished work on behalf of jellespijker September 12, 2025 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants