zed
zed copied to clipboard
Flatpak Build System & Support, v3
ping #6687
This is the third iteration of this PR (v2 here) and uses a different approach to the first two (the process wrapper lib was a maintainability nightmare). While the first two attempted to spawn the necessary processes using flatpak-spawn and host-spawn from the app inside the sandbox, this version first spawns the cli binary which then restart's itself outside of the sandbox using flatpak-spawn. The restarted cli process than can call the bundled app binary normally, with no need for flatpak-spawn because it is already outside of the sandbox. This is done instead of keeping the cli in the sandbox because ipc becomes very difficult and broken when trying to do it across the sandbox.
Overview of changes:
- Add script which generates a flatpak manifest for a given release channel and method from a template.
- The two methods are
copyandbuildwhich either copies the binaries fromtargetor builds them from scratch. - The manifest bundles the cli and app together.
- Added the flatpak-cargo-generator.py script (with minor modifications) needed for offline flatpak builds.
- Added code to cli which detects if it is running in a flatpak sandbox and restarts itself outside it.
- Disabled auto-updating for flatpak's (for now).
- Updated docs with info for flatpaks.
- Added appstream metainfo file which has the app-id, app-name, release notes, and branching colors set per-channel by the manifest.
- Script to generate formatted xml release notes for flatpak from markdown.
Gnome software (example using nightly channel and release notes generated using the script):
Note: The screenshots will no longer work as they aren't being submitted in this PR.
TODO in this PR:
- [x] Make the cli run on host as well
- [x] Remove conditional compilation, check at runtime.
- [x] Set XDG dirs to be in normal flatpak location (since we are escaping the sandbox they are in the normal host location. This is unwanted).
- [x] Disable auto-update.
- [x] Make script to generate manifests for different release channels.
- [x] Add option to package without building
- [x] Support branding colors for different release channels.
- [x] Support release notes per channel.
- [ ] Get thoughts from a design person on metainfo content and screenshots.
- [ ] Get thoughts from a design person about branding-colours. (preview site here). Colours are defined per-release-channel in script/flatpak/generate-manifest.
- [x] ~Figure out how to deal with release-information. (flathub doesn't like long release notes; zed's release notes are pretty long).~ Create script to generate flatpak release notes.
Future work:
- [ ] Auto-update dialog
- [ ] Flatpak auto-update (complete 'Auto-update dialog' first)
- [x] ~Flatpak CI (?).~ Flatpak builds are now identical to linux builds
- [ ] Experimental bundle releases for feedback (?).
(?) = Maybe / Request for feedback
Release Notes:
- N/A
Figure out how to deal with release-information. (flathub doesn't like long release notes; zed's release notes are pretty long).
You could try doing some simple automated summary of the release notes through something like OpenAI's API it shouldn't hallucinate with text summarization, but there is a small risk and it could drop some of the more important changes or focus on minor ones sometimes, but I don't know how else you'd automate it without eiter just trimming after x chars or having separate release summaries for flatpack.
Maybe sorting based on the likes of the linked github issues it closes, then show the top 5 and link to the full release notes at the end? It’s unreasonable to shrink 30+ bullet points into 3 sentences without it being a word soup or completely skipping all of the details, ai isn’t magic. I checked what other large apps like browsers, vscode, lapce, discord, etc. (I know some of them aren’t official) - turns out all of them just have no release notes, so doing this seems to more than enough, it’s very unreasonable to ask large apps to provide 3 sentence release notes.
Maybe sorting based on the likes of the linked github issues it closes, then show the top 5 and link to the full release notes at the end?
For larger releases, avoid endless bullet point lists and rather go with a few paragraphs or a shorter summarized list instead
Seems like that is allowed.
link to the full release notes at the end?
We already have the <url> tag which does that.
This worked better than I expected! It is almost perfect and indistinguishable from directly running zed as non-flatpak app. I was able to open all kinds of directories from home dir and even system dirs. Also, my conda envs worked great inside the zed editor terminal. I was able to flash some android custom ROM with fastboot through USB from the zed terminal. Terminal is almost perfect. Here are few shortcomings I noted though.
- Some env variables gets set automatically set. For example, I get the following when I type this in terminal
❯ echo $XDG_CONFIG_HOME
/home/joel/.var/app/dev.zed.Zed-Dev/config
In my host/outside the flatpak sandbox, XDG_CONFIG_HOME is not set at all. So software that depend on it automatically defaults to ~/.config. But inside zed, it gets set to /home/joel/.var/app/dev.zed.Zed-Dev/config, which breaks software that would normally work. It would nice if we dont let the flatpak runtime/whatever to set these flatpak specific ENV paths somehow. Then it would be perfect.
- Another issue I noted is that my fonts are not accessible by zed now :thinking:. If I remember correctly, in ur previous MR, it kind of worked. Maybe this is also related to ENVs getting set differently inside the zed flatpak app. I dont know.
Finally, a quick doubt though. I checked the permissions for Zed flatpak app using flatseal software. There was no permission granted to access any of the files. But how is Zed able to access them? the terminal, i can understand we may use host-spawn or flatpak-spawn. But I was able to open directories in home or even system dirs as project. Wonder how that was achieved. Is this where zed cli and zed app come into play?
Glad it’s (mostly) working!
- Some env variables gets set automatically set. For example, I get the following when I type this in terminal
Ah, I was intentionally setting those so that the settings et al. would be put in the flatpak directory. Forgot that this would break other things. ~I’ll change it once I think of a nice way to let zeds files be there but nothing else.~ Edit: It's now fixed. Zed's files will still use the flatpak location, but everything else is in the normal stop.
- Another issue I noted is that my fonts are not accessible by zed now 🤔. If I remember correctly, in ur previous MR, it kind of worked. Maybe this is also related to ENVs getting set differently inside the zed flatpak app. I dont know.
Also the xdg env problem. Any non-system fonts which are relative to an xdg dir would break. I thinned the old PR worked because I wasn’t copying the flatpak envs for spawned processes, but here I do want settings and stuff to be in the correct location. Edit: Can you test this again?
Finally, a quick doubt though. I checked the permissions for Zed flatpak app using flatseal software. There was no permission granted to access any of the files. But how is Zed able to access them? the terminal, i can understand we may use
host-spawnorflatpak-spawn. But I was able to open directories in home or even system dirs as project. Wonder how that was achieved. Is this where zed cli and zed app come into play?
So, how this works is that both the main app (the zed-app binary) and the cli (the zed binary) are outside the sandbox. This is why the experience is nearly identical to a normal install. It also means we don’t really need why permissions other than —talk-name=org.freedesktop.Flatpak, which lets us use flatpak-spawn: the command we use to exit the sandbox. Since everything is outside the sandbox, we don’t need any permissions for files. Gnome-software notes this with the “Can acquire arbitrary permissions” note under “Potentially Unsafe” (this is also what I fear the Flathub people may not like, but we would need that permission anyways for the terminal).
Can you test this again?
I gave it a try again. Everything works as expected! Fonts are now accessible. XDG_CONFIG_HOME is no longer set and the program that uses it worked as expected.
So, how this works is that both the main app (the
zed-appbinary) and the cli (thezedbinary) are outside the sandbox. This is why the experience is nearly identical to a normal install. It also means we don’t really need why permissions other than—talk-name=org.freedesktop.Flatpak, which lets us useflatpak-spawn: the command we use to exit the sandbox. Since everything is outside the sandbox, we don’t need any permissions for files. Gnome-software notes this with the “Can acquire arbitrary permissions” note under “Potentially Unsafe” (this is also what I fear the Flathub people may not like, but we would need that permission anyways for the terminal).
Understood. Thanks for the explanation. I was never able to use flatpak version of vscode properly. Sandbox makes less sense for code editors/IDEs. This is much better and works well!
@someone13574 Thanks again!
I like how minimal the code-changes are now - that seems like we're in a good place, and I am happy to merge them after I've had a chance to test it.
The build process I am not yet comfortable with. Overall it is still feeling like a lot of overhead, and I don't understand how the pieces fit together.
My goal is to truly have the minimal "extra" to support each of the (unfortunately numerous) linux package formats; even if that means a bit more work upfront to set things up cleanly.
How minimal can we make the build steps?
- Can we upload things to flathub directly from our CI, or do we have to go via something like https://github.com/flathub/flathub/pull/5253?
- Can we avoid flatpak-cargo-generator and instead wrap the built binaries? If flatpak could happen from the built assets it will be much faster to iterate on, and halves the CI time to make a release.
Other notes:
- re: release notes. Is there any technical restriction, or is this just a preference by the flatpak team. Given that @JosephTLyons spends significant time curating them every week, it seems a shame to not use them. (This would be another reason to have the flatpak build created from the GitHub release - we'd get the real release notes).
- For the images (as @maxdeviant points out) I'm happy to upload them to https://zed.dev and we can link them in instead of adding them to git here.
- Although I know you just changed this, I have a slight bias away from adding yet-more-development-dependencies like meson. We already use
envsubstfor a few things. Maybe we could re-use that here? (Or just use sed, I thought that was ok).
The build process I am not yet comfortable with. Overall it is still feeling like a lot of overhead, and I don't understand how the pieces fit together.
A lot of the overhead is properly handling different release channels and the ability to either rebuild or copy existing binaries.
I'll try to summarise the build process:
- Flatpak's need a manifest which states the permissions and build steps for the package.
- Since this manifest is largely the same between release channels, I thought instead of duplicating 4x, I created a script which changes the things which are needed per-channel by using sed.
- The manifest's build steps are as follows:
- Build using cargo (thus needing flatpak-cargo-generator to get deps) or copy from
target(these commands are subbed in by the manifest generator script I made). - Copy the needed files (desktop entry, icon, and appstream manifest) into the correct spots in the package's filesystem.
- Modify the installed appstream manifest for the release channel (sets the app-id, name, branding colors, and release notes).
- Modify the desktop entry for flatpak (we need to add the
--foregroundarg) and set the icon name per-release channel.
- Build using cargo (thus needing flatpak-cargo-generator to get deps) or copy from
My goal is to truly have the minimal "extra" to support each of the (unfortunately numerous) linux package formats; even if that means a bit more work upfront to set things up cleanly.
Afaik, most packaging formats don't need any changes upstream. Flatpak is just special that way and needs things like an appstream manifest and a flatpak manifest.
How minimal can we make the build steps?
The most minimal way would only having the manifest live in flathub's repos. Then you could drop the manifest generation script and the manifest template. This would make
- Can we upload things to flathub directly from our CI, or do we have to go via something like Add dev.zed.Zed flathub/flathub#5253?
Once the package is on flathub, you can use something like external-data-checker to check for releases and tags on the zed repo and then automatically have a PR created and optionally automatically merged. This will then cause flathub to create a new release.
Alternatively since you get merge privileges to the repo where the manifest is, you can make an action which creates and merges an update PR when you create a release. This could also be tied into automatic release note conversion.
- Can we avoid flatpak-cargo-generator and instead wrap the built binaries? If flatpak could happen from the built assets it will be much faster to iterate on, and halves the CI time to make a release.
If you want to do builds on our CI, then this PR has built in support for copying pre-built binaries instead of rebuilding (since the binaries are identical to normal linux binaries). Removing the ability to build from scratch might not fly with flathub however, as they like doing their own builds so that they are reproducible. Also in their quest for reproducibility, they don't allow network connections for the build part, only the fetch part, so flatpak-cargo-generator.py is needed (though you might be able to make it into a submodule or not have it be in the repo).
- re: release notes. Is there any technical restriction, or is this just a preference by the flatpak team. Given that @ JosephTLyons spends significant time curating them every week, it seems a shame to not use them. (This would be another reason to have the flatpak build created from the GitHub release - we'd get the real release notes).
Sounds like its a preference. This is what the page says: "The following guidelines are not required for submission to Flathub, but are best practices we recommend and consider for curation and promotion. These guidelines are designed to help your app and Flathub itself appear in the best light to users—they may change over time based on developer and user feedback.".
I can remove the modifications to the draft-release-notes script and instead just make a script which just downloads the markdown release notes off of github, converts them to appstream's xml format, and adds them to the release file of the correct channel. Then releases could be completely automated: run a github action which updates the release notes and let external-data-checker automatically trigger a release on flathub.
- For the images (as @ maxdeviant points out) I'm happy to upload them to https://zed.dev and we can link them in instead of adding them to git here.
Sounds good.
- Although I know you just changed this, I have a slight bias away from adding yet-more-development-dependencies like meson. We already use
envsubstfor a few things. Maybe we could re-use that here? (Or just use sed, I thought that was ok).
Sure, I'll revert those commits and look into envsubst.
Since flathub only supports stable and beta releases, not development snapshots like nightly, should I remove support for nightly and dev packaging and try to cut down the build system size and complexity? Zed’s preview releases seem to map to their idea of the beta stream, so that could be either kept or left (you don’t need a separate submission I believe, you just use a different branch of the repo you get access to once the submission is accepted).
@someone13574 I think it's good to keep the channels the same. There are two use-cases: local testing and releasing, for local testing it's nice to be able to work on any branch, and for releasing it's good to fit in with the rest of everything.
I've got this branch running on my laptop and I think I have a bit of a better understanding of how the pieces fit together (at least for the local testing use-case).
I think the ideal "user experience" is that (at least for local development) there's a ./script/flatpak/bundle-linux or something that:
- Builds release binaries with
./script/bundle-linux - Builds a "copy" manifest for the channel read out of the RELEASE_CHANNEL file, and uses the tarball generated by
./script/bundle-linux - Generates the flatpak bundle with that manifest.
So, to simplify from where we are right now:
- Remove the dynamic channel selection (it should be based on the contents of the RELEASE_CHANNEL file)
- Remove the "build" manifest (I really don't want to have to maintain two independent build processes going forward)
- (maybe) Replace generate-manifest with a script that does all three steps (I'm not sure how useful it is to have just a manifest unless we set the source to something that's not a local directory?).
From reading the docs at https://docs.flatpak.org/en/latest/manifests.html, it seems like the archive source is designed to do exactly what we want here.
Also a nitpick: The scripts need set -euo pipefail at the top; so that they exit when they error.
@ConradIrwin
I think the ideal "user experience" is that (at least for local development) there's a ./script/flatpak/bundle-linux or something that:
- Builds release binaries with ./script/bundle-linux
- Builds a "copy" manifest for the channel read out of the RELEASE_CHANNEL file, and uses the tarball generated by ./script/bundle-linux
- Generates the flatpak bundle with that manifest.
Yes, I think that would be better for local development.
- Remove the "build" manifest (I really don't want to have to maintain two independent build processes going forward)
This will cause problems if we submit to flathub. They really dislike not building from source unless absolutely necessary, and it would mean that unless zed has aarch linux bundles being published, we wouldn't have those either which flathub is also very against unless there is a very good reason.
Maybe we can only have the "from-source" manifest in the flathub repo and keep everything here local? Alternatively, I found that using sed to remove regex fenced areas of the manifest is much nicer than using sed to put them in.
The concern definitely makes sense. I do want to see if we can avoid it though, because I don't want to have to debug problems caused by different compiler versions, linkers, C-libraries etc. (It also takes nearly 30m to build zed from scratch, and I'd rather have releases out in 30m instead of 60!). But obviously people have different things they consider "good reasons".
We'd also like to provide aarch64 builds, so probably that can be done in a similar way/timeline.
One thing I've just realized I don't understand while we're talking about this:
- For the .tar.gz we include a bunch of shared libraries that zed needs but which aren't installed on every system. Does flatpak have a way of depending on other packages or of bundling needed .so files?
The failure mode I'm worried about is that someone tries to install the flatpak on a machine missing libasound or libvulkan etc. and it just silently fails to boot for them.
It also takes nearly 30m to build zed from scratch, and I'd rather have releases out in 30m instead of 60!
I think there's a misunderstanding here. The "build from scratch" mode wouldn't be running on Zed's build servers, it would be on Flathub's; so build times would be unaffected. It might take another 30 minutes for a Flathub release to be deployed by them, but there would already be a delay because their releases aren't instant and may have a backlog anyways (iirc they only check the manifest repo once an hour).
I don't want to have to debug problems caused by different compiler versions, linkers, C-libraries etc.
Fair enough. I guess we roll without the build mode, see what they say, and move on from there.
The failure mode I'm worried about is that someone tries to install the flatpak on a machine missing libasound or libvulkan etc. and it just silently fails to boot for them.
I think that normally the freedesktop sdk provides those libraries, but since we’re running outside of the sandbox I'm not sure whether or not they will be actually available. I'll look into it. Edit: I’m going to try to load them outside the sandbox. Zed seems to crash on first attempt. I’ll investigate some more tomorrow.
@someone13574 This looking pretty good to me. I'll go in and tidy up the manifest details a bit, but otherwise I think this is good to go.
Could you please attach those screenshots you had and I'll upload them to zed.dev
Are there other things on your radar before we ship this? If not, let's merge it, and then figure out flat hub support next.
@someone13574 This looking pretty good to me. I'll go in and tidy up the manifest details a bit, but otherwise I think this is good to go.
Could you please attach those screenshots you had and I'll upload them to zed.dev
Are there other things on your radar before we ship this? If not, let's merge it, and then figure out flat hub support next.
I’m not at my computer right now, but I’ll attach when I get home.
I’d like to do a few more things before merging: cleanup the release note script and figure out what causes the crash when I try using ld_library_path to use the platform and sdk shared libs outside the sandbox. I’ll unmark it as a draft once I’m ready.
In a follow-up PR I’ll make a GitHub action for making bundles which automates the download a released tar, updating of the meta info release notes, and adding the .flatpak to the assets of that release. Pushing to flathub can be added after the submission process has been done.
Hi, as someone very interested on this work (and completely amazed by all the effort so far), I'd like to express a few thoughts, which could hopefully instigate further improvements in the future.
Personally, I have a few concerns regarding how the current approach works. As previously noted, it works by fully escaping the Flatpak sandbox during runtime. I'd like to list two important consequences of this:
-
Portability: As I see it, the sandbox is supposed to ship with the dependencies and environment needed for the binary, provided by the Sdk, extensions and Flatpak overrides. This is key to having a Flatpak app run properly across multiple distros, as exotic or minimal as their system may be. However, running the binary on the host will generally attempt to (for example) use its libraries, its environment variables, as well as its paths, and so on, instead of those at the sandbox, whereas there are no guarantees the host will support it all in the same manner, which can lead to inconsistencies or even crashes. While I see there has been an attempt to use
LD_LIBRARY_PATHto mitigate an important part of this problem (essential dynamic libraries), I'm afraid this could still not be enough; for example, NixOS users (using NixOS users as an example, as I am one!) often cannot execute binaries which weren't built by Nix due to the location ofldin the system, and I'm not sure to which extentLD_LIBRARY_PATHsolves this (would be nice to have this tested, especially with third-party binaries, such as compilers, downloaded by Zed). In addition, environment variables, paths and other components of the sandbox's environment might not be present in the host; for example, Zed, having been built targeting the Flatpak's sandbox, may wrongly assume that a directory named/libexists, or that binaries are installed to/binor/usr/bin(those two assumptions don't hold true in NixOS), whereas the assumptions are correct in the sandbox (which is where one would expect the binary to run, in theory). -
Lack of control: The app running fully detached from the sandbox means that most, if not all, sandbox settings and overrides are ignored. This means that environment variables set through an override in Flatseal won't be applied to the final app, in principle, unless the program manually forwards all environment variables it receives - but that could be a bad idea since some of them are specific to the sandbox (hence why XDG-related variables are - cleverly - separately handled by this PR's code, I assume). In addition, one cannot control the availability of certain devices or even of a display server through Flatpak's usual mechanisms (you can use Flatseal to toggle whether an app runs on Wayland or X11, for example, which wouldn't work here unless manually handled somehow). And, of course, you cannot restrict filesystem access to the app, which is one of the main selling points for Flatpak's sandbox; famously, an app, or third-party code or commands run within that app, cannot accidentally
rm -rfyour home directory if you don't let it do so, though that's an extreme (and unhelpful) example - you may also want certain config files to not be visible to the app or otherwise have per-app variations of those config files (e.g.~/.ssh,~/.XCompose, config directories - Flatpak lets you hide those global settings in favor of per-app settings, which is very useful).
Overall, the feeling I get is that the initial outcome of this approach is that Zed will work entirely differently from all other Flatpak apps, since you cannot use any of Flatpak's usual mechanisms and utilities for portability and control. This is unfortunate, as I can use other editors through Flatpak's sandbox just fine. For example, I use VSCodium and several JetBrains IDEs through Flatpak without (at least explicitly) escaping the sandbox at any moment - I just give them access to the folders I expect to be editing code at, add some per-app configuration at the sandbox's $HOME if needed, and third-party binaries and tools not available in the sandbox through SDKs/Extensions can be independently downloaded into the sandbox (Jetbrains IDEs even do this automatically, much like Zed).
With that said, I recognize that this PR, with an overall very clever implementation of what it aims to achieve (to run the binary outside the sandbox), might be the best compromise for now, since the previous attempts of integrating the Zed with the sandbox, all brilliantly led by this PR's author - thank you very much @someone13574 for your efforts! -, unfortunately didn't move forward. Thus, I think the best we can do for now within this PR's scope is issue a clear disclaimer on the README and on the Flatpak's description (and other places) to make sure users are aware of those shortcomings, since they won't be able to use this Flatpak in ways they would normally expect. I hope that, some day, we will be able to work around the shortcomings from previous attempts and come to a solution in which Zed and Flatpak interact nicely together; for now, while such a solution doesn't arrive, moving forward with this PR's approach might be the most sensible thing to do, as it will certainly allow even more users to try out Zed. I hope my comment at least helps future contributors be aware of which potential limitations to look for. :slightly_smiling_face:
@PgBiel I agree on all the points you made, as well as the potential issue with a flathub submission with this approach, but @ConradIrwin has made it pretty clear that this is the path they want to go down because the maintainability of the approach which stayed inside the PR was pretty terrible.
It could probably be made a a fair bit better by simplifying the process wrapper and being more restrictive on the process calls allowed to run on the host (it was pretty much running everything, but most could have ran inside the sandbox and still worked like normal), but that still wouldn’t fix the issue of flatpak support for any command calls added in the future needing to be considered.
These maintenance problems make the approach from the v2 PR a non-starter from the Zed people’s point of view, and this approach may (read likely) be a non-starter from the flathub people’s point of view, so it’s a bit of a tough spot.
If anyone can think of a way to make all parties happy, I’m all ears, but I think that limited changes and low maintenance are fundamentally at odds with native-like quality inside the sandbox (not that it isn’t possible to get native-like quality in the sandbox, just look at gnome-builder or the v2 PR. It just needs much more widespread changes and a bit extra ongoing maintenance and consideration). Maybe it would be best to not move forward will flatpak support if these aides cannot be reconciled, because flatpak without flathub support is kind of useless but the v2 PR (in its current state at least) was a mess.
Hello i just try to compile the flatpak and i got this error with this PR
- cp assets/licenses.md /tmp/tmp.U4vVktxwwM/zed-dev.app/licenses.md cp: unable to evaluate 'assets/licenses.md': No file or folder of that name
Hello i just try to compile the flatpak and i got this error with this PR
- cp assets/licenses.md /tmp/tmp.U4vVktxwwM/zed-dev.app/licenses.md cp: unable to evaluate 'assets/licenses.md': No file or folder of that name
Whoops, forgot to add the fact that you need to run script/generate-licenses before hand (bundle-linux needs it). I’ll add it to the docs when I’m back at my computer.
Thanks i got issue too because i don't have cargo about
error: no such command: about
I just try its works great for know i made a more detailed review in the weekend
It works great to with nvidia driver so for me we can merge it and it work great
@PgBiel I agree on all the points you made, as well as the potential issue with a flathub submission with this approach, but @ConradIrwin has made it pretty clear that this is the path they want to go down because the maintainability of the approach which stayed inside the PR was pretty terrible.
It could probably be made a a fair bit better by simplifying the process wrapper and being more restrictive on the process calls allowed to run on the host (it was pretty much running everything, but most could have ran inside the sandbox and still worked like normal), but that still wouldn’t fix the issue of flatpak support for any command calls added in the future needing to be considered.
To be honest, I can understand that making widespread changes without a very clear plan can often be a bad idea, so the maintainers are right in holding back, at least initially. I feel like we still haven't reached an ideal solution, and would like to propose we discuss this further. I'm sure we can reach an acceptable compromise with the maintainers if we can reach a fairly reasonable solution to our problems.
Taking a look at the context, I see that there is the intention to use flatpak-spawn for the terminal and other processes, and this appears to be the root of most problems we're facing when trying to adapt Zed to Flatpak. This leads to my question: What's stopping us from running all processes inside the sandbox (and, in principle, not using flatpak-spawn at all)? That's the only approach which achieves portability and full control. For example, running any binaries downloaded by Zed using flatpak-spawn is a non-starter for NixOS users, since they weren't compiled through Nix. But when I use VSCodium and JetBrains IDEs through Flatpak, third-party binaries downloaded through the editors themselves work just fine even if they weren't compiled by Nix, because the sandbox emulates the environment they need. As a consequence, I don't even give permissions to use flatpak-spawn to those editors, because they don't need it!
Now, to be clear: I'm not proposing we make it impossible to break the sandbox. flatpak-spawn, if enabled, can also be used in those editors when you need to use tools from your host machine (that's useful!). However, I don't see exactly why we need to break the sandbox. Sure, by default you won't be able to use binaries from the host - but this is a compromise you make by using Flatpak (which is what those disclaimers in the VSCodium and VSCode Flatpaks are about). If we set that aside, the best part of this is that you can set up the environment for Zed - including the binaries available in the sandbox, as well as configuration files, environment variables and so on - in whichever way you want, which, as I see it, should be the primary goal of being able to use Zed within Flatpak. This is different from spawning the binary entirely in the host (this PR's approach) - but if we are doing that, imo it would make more sense to just install it in the host anyway (there is the convenience of flatpak update, but IIRC Zed has auto-update features anyway).
In other words, it feels like all the extra work might be at risk of throwing away the entire goal of packaging for Flatpak: using the sandbox to our advantage, so I ask: are there major blockers stopping us from just running everything in the sandbox, including the terminal? I know some might perceive it as worse UX (since the host binaries aren't immediately available), but, as I see it, this is just kind of how Flatpak works in the end. Combined with permissive defaults (e.g. we can make all paths available to the Zed Flatpak by default), we can minimize problems with UX and still ensure the sandbox works and Zed respects Flatpak's settings just fine. This would also require the least changes in Zed itself, I (possibly wrongly) assume, thus being easier for the maintainers to work with. Let me know what you think.
Just to test my theory, I downloaded the Linux binary for Zed v0.136.0-pre from GitHub Releases and ran it through the VSCodium Flatpak, and it seems to work without modifications! (Of course, I haven't tested every single feature, but this seems usable so far.)
Perhaps the packaging is the most important step missing; I assume the changes needed to Zed itself would be minimal (or none) to make this work. Feel free to correct me though!
You say you're using VScodium through flatpak. Are you using the version with the limitations described here: https://github.com/flathub/com.vscodium.codium, or is there an approach that doesn't require updating our documentation for everything to say "if you're using flatpak, you have to do X, otherwise do it like X"?.
In particular I'm curious about terminal spawning in your screenshot above, as that seemed to be on the list of features that needed extra work to support in the previous version.
I'm also curious how extensions work (for vscode or for neovim) on Nix. Do you have to use the Nix package manager to install everything?
A few examples of features that we've built or want to build to help people be productive, that I think are hard to do in sandbox mode:
- Downloading, installing and running the correct version of a language server depending on the version of the language used per project.
- Attaching debuggers to running processes
- Building and testing arbitrary processes our users write (and in particular not introducing extra debugging time for them caused by subtle differences between the terminal in zed and the terminal outside of zed).
Hard obviously doesn't mean "unsolvable", but if we can avoid all the work to solve the problem by removing the arbitrary constraints; that is the right choice for where we are in the development cycle of Zed.
I'd like to be able to bring "coding at the speed of thought" to as many people as possible with as little support and maintenance effort as possible. That requires aggressively reducing UX changes and code changes that will only be used in a small set of circumstances, because every time we add more of those, we add more state spaces that we need to test when building new things and debug when trying to reproduce issues.
All that said, I don't have much experience using flatpak or Nix. There's an obvious advantage to us in working in these environments as we can help more users get the work they need to get done done, but there are also huge downsides with trying to ship a Nix-enabled-version-of-Zed and a flatpak-enabled-verison-of-Zed. Ideally we ship Zed as-close-as-is-possible to each platform.
What's stopping us from running all processes inside the sandbox
A good user experience: people expect things (like the terminal) to work. I think I could cut down the use of flatpak-spawn a lot from the amount in the v2 PR however. For example, I think that I could get extensions and git integration working without it and only really need it for the terminal and tasks, but cutting it out altogether gives a pretty bad experience out of the box and I really want to avoid vscode's "solution" of being a popup which says to add these commands to your settings for things to work properly.
and it seems to work without modifications!
Try running anything other than echo which is installed on your computer and report back on how well it works. That terminal is inside the sandbox and thus doesn't see anything other than the most basic of programs.
@someone13574 This is looking good, I need to test it again and will try to get back to you within a few days.
What's stopping us from running all processes inside the sandbox
A good user experience: people expect things (like the terminal) to work. I think I could cut down the use of flatpak-spawn a lot from the amount in the v2 PR however. For example, I think that I could get extensions and git integration working without it and only really need it for the terminal and tasks, but cutting it out altogether gives a pretty bad experience out of the box and I really want to avoid vscode's "solution" of being a popup which says to add these commands to your settings for things to work properly.
I believe there is an important misconception at play: we aren't the ones supposed to fix that, but rather those in charge of Flatpak. Fighting against the underlying technology solves some problems and creates others. What we need is for Flatpak itself to provide an easier way to access the host binaries, for example by mounting the host's /usr/bin in a separate folder (right now, Flatpak arbitrarily forbids this). In my particular case, I have an advantage: I can mount /nix in the sandbox and use all of my host binaries just fine, since they are all in /nix, which isn't blocked by Flatpak. But of course that's not a solution for everybody, since not everybody has Nix installed (this approach isn't restricted to NixOS, but to Nix, which can be installed in any distro - but the average user won't have it installed), so this doesn't immediately solve our problem.
In this sense, as I see it, we have multiple competing requirements: having the editor work in Flatpak across all distros supported by Flatpak; having commands and processes spawned by Zed work properly; and having host binaries work right away. We can't (trivially) satisfy all of them at once, so, in my view:
- Having the editor work across distros is the most important thing. It does work by default, and won't work (for example, for me) if we do it in the way this PR does it.
- Having essential Zed features work is also important. I'm not in the position to test every single one of them, but I could get completion, compile projects and so on.
- Having host binaries work in the terminal is, compared to the requirements above, an inconvenience. And it's one that is much easier to solve: you just need the binaries and the
PATHenvironment variable, both of which can be controlled by Zed itself, without any user intervention. In the most extreme of cases, you can useflatpak-spawn, but again: this is not absolutely necessary. Zed just needs to make the necessary binaries available in thePATH, and that is very much actionable.
and it seems to work without modifications!
Try running anything other than echo which is installed on your computer and report back on how well it works. That terminal is inside the sandbox and thus doesn't see anything other than the most basic of programs.
Of course, the terminal won't see anything you don't make available to it. I installed the VSCode flatpak from scratch, and all I needed to do to make Rust available within the terminal was add the Rust SDK extension (which you are already adding as a dependency to the Flatpak itself, so it will be available to users by default - it is not a dependency of the VSCode flatpak in particular). I also had to enable Wayland support (which would be enabled by default in a Zed flatpak as well, without user intervention).
In my case, I could also extend support for any host binaries by simply modifying the PATH to point to /run/current-system/sw/bin, which is where my host (NixOS) binaries are installed to. This is something that can be done by Zed itself as well, but we are sadly limited here by the fact that Flatpak, for some reason, stops us from mapping /bin (path used by most distros for binaries) to the sandbox, so we can't just map the PATH to the host binaries in every distro. Still, we can map to other directories (perhaps created by Zed itself), and using flatpak-spawn as needed is still viable.
And still, this potential work I describe is really only needed for the single problem that is discovering binaries. As I see it, it's not enough of a justification to fully escape the sandbox and potentially deny any chances of the Zed official Flatpak being approved into Flathub. Especially because it's solvable - the binaries and the PATH are all you need.
You say you're using VScodium through flatpak. Are you using the version with the limitations described here: https://github.com/flathub/com.vscodium.codium, or is there an approach that doesn't require updating our documentation for everything to say "if you're using flatpak, you have to do X, otherwise do it like X"?.
The only modifications needed are to use particular binaries within the sandbox, which is something that can be handled by Zed automatically. In my case, I installed the Rust SDK extension (available through Flatpak itself) which added cargo to the terminal, but Zed could just as well install cargo for me and change its own PATH as needed. (This PR adds the Rust SDK extension as a dependency, so, in this particular case, it'd be available by default.)
In particular I'm curious about terminal spawning in your screenshot above, as that seemed to be on the list of features that needed extra work to support in the previous version.
It worked out of the box.
I'm also curious how extensions work (for vscode or for neovim) on Nix. Do you have to use the Nix package manager to install everything?
For VSCode outside Flatpak, perhaps (I don't know the specifics); for VSCode inside Flatpak, nope. Which is why using Zed in Flatpak is so attractive to me - I don't have to care about the platform or other specifics, in the sandbox everything Just Works.
A few examples of features that we've built or want to build to help people be productive, that I think are hard to do in sandbox mode:
- Downloading, installing and running the correct version of a language server depending on the version of the language used per project.
I tested this on a Gleam project too, running Zed on top of a fresh install of the VSCode Flatpak (thus no modifications to the PATH), and pressing "Yes" on the install LSP button worked right away. I assume this feature wouldn't face significant obstacles.
- Attaching debuggers to running processes
I assume there might be complications in trying to attach debuggers to processes running outside of the Flatpak sandbox, but for those running in the same sandbox, I don't see why it wouldn't work in principle.
I'm not sure it's worth it to add support for this feature in a fully complete way (which also works for processes outside of the sandbox) at this moment. I'd take this as simply a tradeoff in using Flatpak; perhaps a proper solution could be found in the future (unfortunately I'm not very knowledgeable on this part).
- Building and testing arbitrary processes our users write (and in particular not introducing extra debugging time for them caused by subtle differences between the terminal in zed and the terminal outside of zed).
The differences here would be similar to differences between one machine and another, or between one container and another: your environment is slightly different, so it's natural that there would be differences. You should test in whichever environment you'd like to prioritize, as I see it.
Hard obviously doesn't mean "unsolvable", but if we can avoid all the work to solve the problem by removing the arbitrary constraints; that is the right choice for where we are in the development cycle of Zed.
I understand your position, but, as I see it, "removing the constraints" here would consist of denying the entirety of Flatpak's features for what is simply running a binary which should otherwise have been installed in the host. I'm not sure the tradeoff here is worth it; I'd rather not mislead users into thinking there is actual Flatpak support for Zed, if this approach is ultimately chosen.
I'd like to be able to bring "coding at the speed of thought" to as many people as possible with as little support and maintenance effort as possible. That requires aggressively reducing UX changes and code changes that will only be used in a small set of circumstances, because every time we add more of those, we add more state spaces that we need to test when building new things and debug when trying to reproduce issues.
All that said, I don't have much experience using flatpak or Nix. There's an obvious advantage to us in working in these environments as we can help more users get the work they need to get done done, but there are also huge downsides with trying to ship a Nix-enabled-version-of-Zed and a flatpak-enabled-verison-of-Zed. Ideally we ship Zed as-close-as-is-possible to each platform.
Fully understandable. I'd say that what we would need to do here is mostly inform users (perhaps through a single docs page - so, not everywhere!) that Flatpak is an entirely different platform running within your system. It's like if you ran a Debian container in your system. Differences are to be expected - but you'll still be able to code at the speed of thought, as long as you know how Flatpak works and the tradeoffs involved. The most important tradeoff is that host binaries are not accessible by default, which can be solved either by the user - which can manually install the binaries in the sandbox, much like you'd install in a container - or by Zed itself - by installing the binaries in a certain path and adding it to $PATH.
It worked out of the box.
I guess we have different views of what "out of the box" means in this case. I view "out of the box" as meaning that the terminal would function like a normal terminal on the host system, being able to access everything normally. This isn't too difficult of a change to make and there is precedence of flathub allowing --talk-name=org.freedesktop.Flatpak for this specific use-case in applications such as gnome-builder. @ConradIrwin Its ultimately up to you, but I'd be willing to try to take another shot at the v2 approach but with much more running in the sandbox (likely limiting it to a few processes) and an attempt to cut down the process wrapper crate to maybe a single function (something like convert_to_flatpak(command: std::process::Command)). All the packaging changes from this PR would be very easy to move over, and a lot could be taken from the v2 PR as well.