commit 5421db2960d92801edc7f882a08ffc8e8776e478 Author: pc-heini Date: Mon Jun 15 09:29:55 2026 +0200 Initial O3DE Flatpak packaging + Gitea CI Repackage the official O3DE Linux .deb as a Flatpak and publish it as a static OSTree repo on the 'pages' branch for install via flatpak remote. - org.o3de.O3DE.yaml: flatpak-builder manifest (extracts the .deb into /app) - o3de-wrapper.sh: launcher that locates the versioned o3de binary at runtime - desktop + AppStream metadata under the app-id - scripts/: live version resolver and local build helper - .gitea/workflows/build-flatpak.yml: daily check -> build -> publish -> tag Co-Authored-By: Claude Opus 4.8 diff --git a/.gitea/workflows/build-flatpak.yml b/.gitea/workflows/build-flatpak.yml new file mode 100644 index 000000000..4a146b53a --- /dev/null +++ b/.gitea/workflows/build-flatpak.yml @@ -0,0 +1,139 @@ +name: Build and Publish O3DE Flatpak + +on: + schedule: + - cron: '0 2 * * *' # daily at 02:00 - checks for a new O3DE release + workflow_dispatch: + inputs: + force: + description: 'Rebuild even if this version was already published' + type: boolean + default: false + +permissions: + contents: write + +jobs: + build: + # Adjust the label to match your registered act_runner. The runner needs a + # lot of free disk (O3DE is ~15-18 GB installed; the build needs ~2-3x that) + # and the container must be privileged so Flatpak's sandbox (bubblewrap) works. + runs-on: ubuntu-latest + container: + image: ubuntu:24.04 + options: --privileged + steps: + - name: Install build dependencies + run: | + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + ca-certificates curl git jq xz-utils zstd binutils \ + flatpak flatpak-builder + + - name: Checkout + uses: actions/checkout@v4 + + - name: Resolve latest O3DE version + id: ver + run: | + chmod +x scripts/*.sh + eval "$(scripts/get-latest-version.sh)" + { + echo "version=$version" + echo "deb_url=$deb_url" + echo "deb_file=$deb_file" + echo "sha256=$sha256" + } >> "$GITHUB_OUTPUT" + echo "Latest O3DE: $version ($deb_file)" + + - name: Decide whether to build + id: check + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + if [ "${{ inputs.force }}" = "true" ]; then + echo "build=true" >> "$GITHUB_OUTPUT" + echo "Force build requested." + elif git ls-remote --tags origin "refs/tags/v${{ steps.ver.outputs.version }}" | grep -q .; then + echo "build=false" >> "$GITHUB_OUTPUT" + echo "v${{ steps.ver.outputs.version }} already published - nothing to do." + else + echo "build=true" >> "$GITHUB_OUTPUT" + echo "New version v${{ steps.ver.outputs.version }} - building." + fi + + - name: Install Flatpak runtime and SDK + if: steps.check.outputs.build == 'true' + run: | + flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + flatpak install -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08 + + - name: Download O3DE .deb + if: steps.check.outputs.build == 'true' + run: | + curl -fL --retry 3 -o o3de.deb "${{ steps.ver.outputs.deb_url }}" + if [ -n "${{ steps.ver.outputs.sha256 }}" ]; then + echo "${{ steps.ver.outputs.sha256 }} o3de.deb" | sha256sum -c - + else + echo "::warning::No published checksum; skipping verification." + fi + + - name: Stamp version into AppStream metadata + if: steps.check.outputs.build == 'true' + run: | + sed -i -E \ + "s###" \ + org.o3de.O3DE.metainfo.xml + + - name: Build Flatpak into OSTree repo + if: steps.check.outputs.build == 'true' + run: | + flatpak-builder --disable-rofiles-fuse --force-clean \ + --repo=repo --default-branch=stable \ + build-dir org.o3de.O3DE.yaml + flatpak build-update-repo repo \ + --title="O3DE (unofficial Flatpak)" \ + --prune --prune-depth=1 + # Free disk before publishing (the repo/ snapshot is all we still need). + rm -rf build-dir .flatpak-builder o3de.deb data + + - name: Generate .flatpakrepo + if: steps.check.outputs.build == 'true' + run: | + BASE="${{ github.server_url }}/${{ github.repository }}/raw/branch/pages" + cat > repo/o3de.flatpakrepo < **Status:** community / unofficial. O3DE is a large application (~15–18 GB +> installed); building and hosting it is heavy. Treat this as best-effort. + +--- + +## Installing (end users) + +```sh +# Flathub provides the runtime O3DE needs +flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + +# Add this repo (replace with the Gitea account that owns the repo) +flatpak remote-add --if-not-exists o3de \ + https://gitea.pc-heini.de//o3de-flatpak/raw/branch/pages/o3de.flatpakrepo + +flatpak install o3de org.o3de.O3DE +flatpak run org.o3de.O3DE +``` + +Later updates: + +```sh +flatpak update org.o3de.O3DE +``` + +> The repo is currently **unsigned** (no GPG). Flatpak will add it with GPG +> verification disabled. See *Signing* below to harden this. + +--- + +## How it works + +| File | Purpose | +| --- | --- | +| `org.o3de.O3DE.yaml` | `flatpak-builder` manifest. Unpacks the official `o3de_*.deb` into `/app` and wires up a launcher. | +| `o3de-wrapper.sh` | Entry point. Finds the versioned `o3de` Project Manager binary inside the sandbox and sets `LD_LIBRARY_PATH`. | +| `org.o3de.O3DE.desktop` | Desktop entry under the Flatpak app-id. | +| `org.o3de.O3DE.metainfo.xml` | AppStream metadata (version stamped at build time). | +| `scripts/get-latest-version.sh` | Resolves the latest `.deb` URL, version, and SHA-256 from o3debinaries.org. | +| `scripts/build.sh` | Build + test the Flatpak locally. | +| `.gitea/workflows/build-flatpak.yml` | CI: detect new version → build → publish to `pages` → tag `vX.Y.Z`. | + +The engine ships as a Debian package at a predictable URL +(`https://o3debinaries.org/main/Latest/Linux/o3de_.deb`). The build extracts +it (`ar` + `tar`) and copies the payload into the Flatpak's `/app`. The version +directory inside the `.deb` changes every release, so the wrapper discovers the +executable at runtime rather than hard-coding a path. + +--- + +## CI requirements (Gitea Actions) + +The workflow targets a **self-hosted `act_runner`**. Because O3DE is large: + +- **Disk:** budget **60 GB+** free. The build needs roughly 2–3× the installed + size (extracted payload in `build-dir` + a copy committed into the OSTree + `repo/`). The job deletes `build-dir` before publishing to cut peak usage, but + it can still be tight. If builds fail on space, that's the first thing to check. +- **Privileged container:** Flatpak's sandbox (bubblewrap) needs it. The job sets + `options: --privileged`; your runner's `config.yaml` must allow privileged + containers (or run jobs in host mode with `flatpak`/`flatpak-builder` installed + on the host). +- **Runner label:** the job uses `runs-on: ubuntu-latest`. Change it if your + runner is registered with a different label. +- **Token:** publishing force-pushes the `pages` branch and creates a `vX.Y.Z` + tag. The auto-provided `GITHUB_TOKEN` (with `contents: write`) usually suffices. + If your instance restricts it, create a Personal Access Token with repo write + access and add it as a secret named **`PUBLISH_TOKEN`** — the workflow prefers + it automatically. + +Trigger it manually from the Gitea Actions UI (`workflow_dispatch`, with an +optional **force** rebuild), or let the daily `cron` run it. It only rebuilds when +the upstream version has no matching `vX.Y.Z` tag yet, so reruns are cheap no-ops. + +--- + +## Building locally + +```sh +sudo apt install flatpak flatpak-builder # or your distro's equivalent +./scripts/build.sh +``` + +Test without installing: + +```sh +flatpak-builder --run build-dir org.o3de.O3DE.yaml o3de-wrapper.sh +``` + +--- + +## Signing (recommended hardening) + +The first iteration publishes an unsigned repo for simplicity. To sign: + +1. Generate a key: `gpg --quick-gen-key "O3DE Flatpak" default default never` +2. Export the public key and add `GPGKey=` to the generated `.flatpakrepo`. +3. Pass `--gpg-sign=` to both `flatpak-builder` and `build-update-repo`, + and provide the private key to CI via a secret. Until then, users add the + remote with GPG verification disabled. + +--- + +## Caveats & things to verify + +- **The `.deb` internal layout is assumed** (`/opt/O3DE//…` with the + `o3de` binary under `bin/Linux/…`). If a future release changes this, adjust + `o3de-wrapper.sh` and the manifest's copy commands. The first real build will + confirm it. +- **GPU / drivers:** the renderer needs working GPU access. The manifest grants + `--device=dri`/`--device=all`; on some setups you may also want the matching + GPU driver extension from Flathub. +- **Sandbox filesystem:** `--filesystem=home` lets the Project Manager create and + open projects under your home directory. Tighten or widen to taste. +- **Hosting via raw branch URLs** works because Flatpak fetches individual files + (`summary`, `config`, `objects/…`). Gitea serves these from the `pages` branch. + If you later put a real static web host in front of it, just change `Url=` in + the `.flatpakrepo`. + +--- + +*Not affiliated with or endorsed by the Open 3D Foundation. O3DE is licensed under +Apache-2.0 / MIT.* diff --git a/o3de-wrapper.sh b/o3de-wrapper.sh new file mode 100755 index 000000000..a1f0bef58 --- /dev/null +++ b/o3de-wrapper.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Launcher for the O3DE Project Manager inside the Flatpak sandbox. +# +# The Debian package installs O3DE under /opt/O3DE//, which becomes +# /app/opt/O3DE// inside the Flatpak. The version directory name +# changes with every release, so we discover the executable at runtime instead +# of hard-coding a path. +set -eu + +O3DE_ROOT=/app/opt/O3DE + +# Bundled shared libraries that ship inside the .deb. +export LD_LIBRARY_PATH="/app/lib:${O3DE_ROOT}/lib:${LD_LIBRARY_PATH:-}" + +# Locate the Project Manager executable ("o3de"). +O3DE_BIN=$(find "$O3DE_ROOT" -type f -name o3de -path '*bin/Linux*' 2>/dev/null | head -n 1) +if [ -z "$O3DE_BIN" ]; then + O3DE_BIN=$(find "$O3DE_ROOT" -type f -executable -name o3de 2>/dev/null | head -n 1) +fi + +if [ -z "$O3DE_BIN" ]; then + echo "error: O3DE executable not found under $O3DE_ROOT" >&2 + echo " (the .deb layout may have changed)" >&2 + exit 1 +fi + +# Make libraries that sit next to the binary discoverable too. +export LD_LIBRARY_PATH="$(dirname "$O3DE_BIN"):${LD_LIBRARY_PATH}" + +exec "$O3DE_BIN" "$@" diff --git a/o3de.flatpakrepo b/o3de.flatpakrepo new file mode 100644 index 000000000..e17a5285f --- /dev/null +++ b/o3de.flatpakrepo @@ -0,0 +1,10 @@ +[Flatpak Repo] +Title=O3DE (unofficial Flatpak) +# Replace with the Gitea account/org that owns this repo. +# The CI job regenerates this file on the 'pages' branch with the correct URL, +# so the canonical copy to use is: +# https://gitea.pc-heini.de//o3de-flatpak/raw/branch/pages/o3de.flatpakrepo +Url=https://gitea.pc-heini.de//o3de-flatpak/raw/branch/pages +Homepage=https://o3de.org/ +Comment=Unofficial O3DE engine repackaged as a Flatpak +Description=Install the Open 3D Engine on any Linux distribution via Flatpak. diff --git a/org.o3de.O3DE.desktop b/org.o3de.O3DE.desktop new file mode 100644 index 000000000..688309b88 --- /dev/null +++ b/org.o3de.O3DE.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Type=Application +Name=O3DE +GenericName=3D Engine +Comment=Open 3D Engine - real-time 3D engine for games and simulations +Exec=o3de-wrapper.sh +Icon=org.o3de.O3DE +Terminal=false +Categories=Development;Graphics;3DGraphics; +Keywords=game;engine;3d;simulation;editor; +StartupNotify=true +StartupWMClass=O3DE diff --git a/org.o3de.O3DE.metainfo.xml b/org.o3de.O3DE.metainfo.xml new file mode 100644 index 000000000..e40e99f1a --- /dev/null +++ b/org.o3de.O3DE.metainfo.xml @@ -0,0 +1,49 @@ + + + org.o3de.O3DE + + O3DE + Open 3D Engine - real-time 3D engine for games and simulations + + CC0-1.0 + Apache-2.0 OR MIT + + + Open 3D Foundation + + + +

+ Open 3D Engine (O3DE) is an Apache 2.0-licensed, open-source, real-time 3D + engine for building games and simulations, with a fully featured editor, + multi-threaded photorealistic renderer, and an extensible asset pipeline. +

+

+ This is an unofficial, community-maintained Flatpak repackaging of the + official O3DE Linux binaries so the engine can be installed on any Linux + distribution, not only Debian/Ubuntu. +

+
+ + org.o3de.O3DE.desktop + + https://o3de.org/ + https://docs.o3de.org/ + https://github.com/o3de/o3de/issues + + + Development + Graphics + + + + + + + + +

Placeholder release - rewritten automatically at build time.

+
+
+
+
diff --git a/org.o3de.O3DE.yaml b/org.o3de.O3DE.yaml new file mode 100644 index 000000000..b734536b4 --- /dev/null +++ b/org.o3de.O3DE.yaml @@ -0,0 +1,55 @@ +# flatpak-builder manifest for repackaging the official O3DE Linux .deb as a Flatpak. +# +# The workflow (and scripts/build.sh) download the latest o3de_*.deb to ./o3de.deb +# next to this manifest before building, so the manifest itself never needs editing +# when a new version drops. +id: org.o3de.O3DE +runtime: org.freedesktop.Platform +runtime-version: '24.08' +sdk: org.freedesktop.Sdk +command: o3de-wrapper.sh + +finish-args: + - --share=ipc + - --share=network # Project Manager fetches gems/templates; engine downloads assets + - --socket=x11 + - --socket=fallback-x11 + - --socket=wayland + - --socket=pulseaudio + - --device=dri # GPU access for the renderer + - --device=all # broader device access (input devices, additional GPUs) + - --filesystem=home # O3DE stores projects and ~/.o3de in the user's home + - --talk-name=org.freedesktop.Notifications + - --env=QT_QPA_PLATFORM=xcb # O3DE's bundled Qt is most reliable under XWayland/X11 + +modules: + - name: o3de + buildsystem: simple + build-commands: + # The .deb is an `ar` archive containing data.tar.{gz,xz,zst}. + - ar x o3de.deb + - mkdir -p data + - tar -C data -xf data.tar.* + # The payload lays files out under /opt (engine) and /usr (desktop/icon glue). + - 'if [ -d data/opt ]; then mkdir -p "${FLATPAK_DEST}/opt"; cp -a data/opt/. "${FLATPAK_DEST}/opt/"; fi' + - 'if [ -d data/usr ]; then cp -a data/usr/. "${FLATPAK_DEST}/"; fi' + # Launcher + AppStream + desktop entry under the Flatpak app-id. + - install -Dm755 o3de-wrapper.sh "${FLATPAK_DEST}/bin/o3de-wrapper.sh" + - install -Dm644 org.o3de.O3DE.desktop "${FLATPAK_DEST}/share/applications/org.o3de.O3DE.desktop" + - install -Dm644 org.o3de.O3DE.metainfo.xml "${FLATPAK_DEST}/share/metainfo/org.o3de.O3DE.metainfo.xml" + # Pick up an icon from the .deb if one is present and rename it to the app-id. + - | + icon=$(find data -type f \( -name '*o3de*.png' -o -name '*o3de*.svg' \) 2>/dev/null | head -n1) + if [ -n "$icon" ]; then + ext="${icon##*.}" + install -Dm644 "$icon" "${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/org.o3de.O3DE.${ext}" + fi + sources: + - type: file + path: o3de.deb + - type: file + path: o3de-wrapper.sh + - type: file + path: org.o3de.O3DE.desktop + - type: file + path: org.o3de.O3DE.metainfo.xml diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 000000000..4785e0a69 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Build the O3DE Flatpak locally (for testing the manifest before relying on CI). +# +# Requires: flatpak, flatpak-builder, curl, and the Flathub remote. +# Note: O3DE is large (~15-18 GB installed); expect a multi-GB download and a +# build that needs a lot of free disk space. +set -euo pipefail +cd "$(dirname "$0")/.." + +eval "$(scripts/get-latest-version.sh)" +echo ">> Latest O3DE: ${version} (${deb_file})" + +if [ ! -f o3de.deb ]; then + echo ">> Downloading ${deb_url}" + curl -fL --progress-bar -o o3de.deb "${deb_url}" +fi + +if [ -n "${sha256:-}" ]; then + echo ">> Verifying checksum" + echo "${sha256} o3de.deb" | sha256sum -c - +else + echo ">> No checksum published; skipping verification" >&2 +fi + +# Make sure the runtime/SDK are available (no-op if already installed). +flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo +flatpak install --user -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08 || true + +echo ">> Building" +flatpak-builder --user --force-clean --install-deps-from=flathub \ + --repo=repo build-dir org.o3de.O3DE.yaml + +cat <> Done. + Test run without installing: + flatpak-builder --run build-dir org.o3de.O3DE.yaml o3de-wrapper.sh + Or install from the local repo: + flatpak remote-add --user --no-gpg-verify o3de-local repo + flatpak install --user o3de-local org.o3de.O3DE +EOF diff --git a/scripts/get-latest-version.sh b/scripts/get-latest-version.sh new file mode 100755 index 000000000..80110830d --- /dev/null +++ b/scripts/get-latest-version.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Resolve the latest official O3DE Linux .deb. +# +# Prints shell-eval-able key=value lines: +# version=26.05.0 +# deb_url=https://o3debinaries.org/main/Latest/Linux/o3de_2605_0.deb +# deb_file=o3de_2605_0.deb +# sha256= +# +# Usage: eval "$(scripts/get-latest-version.sh)" +set -euo pipefail + +INDEX="https://o3debinaries.org/download/linux.html" + +# The download index links to the current stable .deb under main/Latest. +DEB_URL=$(curl -fsSL "$INDEX" \ + | grep -oE 'https://o3debinaries\.org/main/Latest/Linux/o3de_[0-9_]+\.deb' \ + | head -n1 || true) + +if [ -z "${DEB_URL}" ]; then + echo "error: could not find an o3de_*.deb link on ${INDEX}" >&2 + exit 1 +fi + +DEB_FILE=$(basename "$DEB_URL") # e.g. o3de_2605_0.deb +RAW=${DEB_FILE#o3de_}; RAW=${RAW%.deb} # e.g. 2605_0 +# 2605_0 -> 26.05.0 (YYMM_patch -> YY.MM.patch) +VERSION=$(printf '%s' "$RAW" | sed -E 's/^([0-9]{2})([0-9]{2})_([0-9]+)$/\1.\2.\3/') + +SHA256=$(curl -fsSL "${DEB_URL}.sha256" 2>/dev/null | awk 'NR==1{print $1}' || true) + +echo "version=${VERSION}" +echo "deb_url=${DEB_URL}" +echo "deb_file=${DEB_FILE}" +echo "sha256=${SHA256}"