An 'xdg-app' is a way of distributing and running applications with more isolation from the system than a traditional packaging format such as RPM. Dependencies for an xdg-app are either distributed as part of the runtime or are bundled into the application itself. These - the runtime and the application - are the two types of artifacts we want to build for Fedora.
- A runtime contains files that multiple applications depend on. There can be any number of runtimes installed on a system: for example, there might be both a Fedora 23 and a Fedora 24 runtime installed. A runtime looks like a mini-system image with libraries in /usr/lib, data files in /usr/share, binaries in /usr/bin and so forth.
- The application contains both the application itself and libraries it depends on that are not part of the runtime. All files in the application are under /app.
When a xdg-app is run, an isolated environment is created with the runtime mounted on /usr and the application mounted on /app. Depending on sandboxing, the environment might have full access to the user's home directory, or might only access to a restricted set of D-Bus portals.
We generally want the runtimes and applications to be built out of the same set of sources as the rest of Fedora: when we do a security update for a library, we want to know what applications or runtimes are affected and need to be rebuilt. We don't want to create an entirely new way for sources to get into Fedora bypassing the normal Fedora procedures.
Runtimes can simply be built out of normal Fedora RPMS in the same way as we might compose an ISO or a container image, but to make an application out of RPMs requires rebuilding them with the /app prefix. The most obvious way of doing this would be a separate build target, but the downside of this is that we've now forked the build process. Say we build the 'eog' image view as an xdg-app - so we rebuild it in the special build target. It requires the 'exempi' library for reading image metadata, so we rebuild that as well. Later - the exempi maintainer updates exempi - somehow the build in the other build target has to be rebuilt in sync, or the eog bundle will contain a stale version of exempi.
What if we could consider "x86_64 but rebuilt with a /app prefix" as a separate architecture, so that whenever exempi is rebuilt, koji rebuilds that version as well? This led to the idea of "architecture variants".
- In the Koji web interface (and most of the code) an architecture variant is represented by a string like x86_64~app.
- Architecture variants are built as the base architecture with a different RPM configuration to change the prefix. (Adding an actual extra architecture would require extensive changes to RPM, autoconf, etc.)
- The RPM configuration also changes the dist tag, so the rebuilt eog RPM has a name like eog-3.20.0-1.fc24~app.x86_64.rpm. Making eog-3.20.0-1.fc24.x86_64~app.rpm would be much trickier - it would require all the RPM, autoconf, etc, changes.
- By default packages are built only for the base architectures - each package has to be configured explicitly to be built for variants.
- A packager identifies a package as a candidate for creating a xdg-app for.
- They mark the application to be built as an app (koji set-pkg-variants 'MAIN app' f25 eog.)
- They bump and rebuild the package
- They try and build the xdg-app (koji xdg-app-build f25 eog eog.json. Extra information about the app - like what resources it wants access to - is included in a JSON file that could also be checked into source control.
- If that fails because of missing library dependencies, they add the app variant to these dependencies and rebuild them, and repeat the xdg-app build.
Phase 1 - manual enablement
- Support in koji for x86_64+app architectures. These architectures have have different RPM configurations so that things are installed in /app rather than user. They are also “multiarch”, so that packages from the base arch are pulled in when building.
- A way to add these extra architectures to a particular package in a particular tag - probably done as a koji plugin adding ‘xdgapp-mark.’ (Currently it only seems possible to set extra architectures when adding a package to a tag, and only for an admin.)
- A koji plugin to add ‘koji xdgapp-build [--runtime] NVR’ which takes an existing package that has been built for the +app architectures, and converts the RPM and it’s dependencies into a xdg-app bundle (either existing ostree delta or future OCI image).
Enhancement: autoimport into a ostree repository
- When new app/runtime bundles are built, automatically import them into a ostree repository. (Or testing/release repositories based upon how the source rpms are tagged) Conceivably this could be handled by a new separate service that listens on the message bus, rather than trying to extend koji.
Enhancement: autorebuild of xdg-app bundles
- When packages are rebuilt that are part of xdg-app apps and runtimes, automatically trigger rebuilds of the runtimes. This would require tracking the packages in each app or runtime. This might be handled by the same daemon as above.
Enhancement: generalize this to server containers
- The basic idea of taking RPMs and converting the rpm and dependencies into a container via rpm-ostree is applicable to containers as well. The autorebuild and autoimport into ostree steps would be useful for this as well (but also probably auto-push to a docker registry.) One challenge here is that while an RPM of a desktop application is “self-describing” - it contains the .desktop and appstream files that specify what the application is and how to run it, turning an RPM of, say, etcd into a useful container probably requires extra metadata and configuration files.
Enhancement: merge in +app architectures to an existing build
- It might be nice to avoid the bump+rebuild, as envisioned by the mergeScratch RPC call that was added https://lists.fedoraproject.org/pipermail/buildsys/2015-April/004628.html
Enhancement: auto-rebuilding dependencies
- Tooling so that when someone wants to build an application that has not previously been built for +app, all the build dependencies are queued for adding to the +app architectures and rebuilt in the right order.