The March Conveyor update makes it simple to define file associations for every OS,
and can automatically release to Amazon S3 and GitHub Releases. It improves the UX of
self-signed apps on Windows, adds a new conveyor run
command and has many usability
upgrades for developers. Let’s dive in!
File associations
Files and folders are critical tools for organizing work and creating complex results. Desktop apps can easily work with files, but the way you associate apps with file types varies across platforms. Conveyor now abstracts you from the details whilst letting you specify OS-specific metadata if you want precise control.
Adding an association for *.myapp
files is as easy as this:
app {
file-associations = [ .myapp ]
}
Linux requires you to specify MIME types for file associations. Conveyor takes care of that for you by generating a MIME
type based on your app’s rdns-name
, specifically application/vnd.${app.rdns-name}.${extension}
. If you prefer to set
the MIME yourself, you can do so like this:
app.file-associations = [ .foo application/x-my-mime-type ]
Some file types may have more than one valid extension, e.g. for an image editor you could write:
app.file-associations += .jpg .jpeg image/jpeg
app.file-associations += .tif .tiff image/tiff
Note here we show how to use the +=
operator to append to the pre-existing list (which starts out empty).
To handle a common extension like .txt
make sure to specify the right MIME type e.g. text/plain
.
Apple has a MIME-like system for its own platforms called Uniform Type Identifiers. Conveyor handles all the details for you, but you can specify your own UTIs if you want.
Automatic deployment
The conveyor make copied-site
command lets you build and immediately upload the generated set of packages, update
metadata site and the download.html
page. Previously this feature only supported SFTP upload, now it knows how to
upload to AWS and GitHub Releases as
well.
Uploading to S3, taking the access key id and secret key from environment variables:
app {
site {
base-url = "https://my-bucket.s3.amazonaws.com/path/to/site"
s3 {
region = "us-east-1"
access-key-id = ${env.AWS_ACCESS_KEY_ID}
secret-access-key = ${env.AWS_SECRET_ACCESS_KEY}
}
}
}
The app.site.copied-to
key is automatically inferred to be s3:my-bucket/path/to/site
.
Uploading to GitHub Releases, for open source projects:
app {
# Tell Conveyor the project is open source.
vcs-url = "github.com/user/repo"
site {
github {
// Token looks like "github_pat_SOME_TOKEN_VALUE"
oauth-token = ${env.GITHUB_TOKEN}
// Optional: upload the download site to a branch.
pages-branch = "gh-pages"
}
}
}
Now when executing conveyor make copied-site
the generated download.html
page will be placed at the root of your
GitHub Pages.
With these new capabilities we’ve now achieved our goal of making deploying desktop apps as easy as deploying a web app: generating a fresh app from scratch is one command, and going from the resulting set of compiled app files to a download site filled with self-updating packages is also one command. For bytecode and scripting languages the only remaining difference is signing certificates.
Improved self-signed UX for Windows
Speaking of which, we improved the end-user experience when you’re not using code signing. Users can now simply run the self-signed installer EXE. Your app will trigger security warnings in Edge which the user must click through, but in Chrome there are no such barriers. The installer will install your code signing certificate into the cert store, meaning that from that point on updates to new versions are properly authenticated, Windows has a stable package identity and admins can whitelist your software as they see fit.
Why the change? Previous versions of Conveyor asked Windows users to copy/paste some PowerShell commands to install self-signed certificates, but this wasn’t always ideal. PowerShell comes in multiple versions and the latest version breaks backwards compatibility. Additionally, different versions of Windows require different incantations to ensure scripts can run. Using an installer to add the certificate gets rid of these problems.
Note that you can still use the .appinstaller
or .msix
files directly, but you’ll need to install the certificate
yourself in that case. The raw files are useful for Windows network admins, but our installer EXE wraps the MSIX
packaging system with various fixes and improvements.
New run command
When testing you frequently want to build your app into packaged form and then execute it. Previously you had to use
the right target for your current host OS, then go into the output
directory and run your program from there. It
wasn’t hard, but it wasn’t as convenient as possible either.
The new conveyor run
command builds the right version of your app for the current OS and then executes it immediately.
Note that for speed it doesn’t install the app, it just creates the directory tree that will be installed, signs it
and then executes the contents. This lets you quickly test that files are laid out correctly and that your app functions
properly when packaged and signed. On macOS there’s no installation process so apps run this way will work
in the same way as when copied to /Applications
.
File system virtualization control
When your app is run on Windows the kernel will virtualize parts of the file system and registry, redirecting writes to an app private location. In this way uninstallation is guaranteed to be clean so your app can’t accidentally contribute to system “rot”, and there are no tricky permissions issues with app data in other user’s home directories because Windows itself is doing the uninstall.
Virtualization also means any sub-components you may ship that write to shared locations like c:\windows
or a
shared AppData
directory can’t conflict with each other, and ensures that Windows can hard link files at install time
from other apps, without any risk of an app modifying them on disk (because any writes trigger copy-on-write redirection).
All very useful! Still, there are times when you may need to opt out:
- If your app is actually intended to modify the data files of another app. For example, Minecraft modding tools.
- If it causes bugs.
The March update lets you control this virtualization feature. Here’s a couple of examples:
app.windows.manifests.msix.virtualization {
# Exclude a single folder within LocalAppData folder from virtualization.
excluded-directories += LocalAppData/OtherAppsFolder
# Exclude the entire RoamingAppData folder from virtualization.
excluded-directories += RoamingAppData
}
Usually you’d only exclude the smallest set of folders you need, but it’s possible to devirtualize the entire AppData
directory for both local and roaming data (roaming = copied from the user’s home directory server on login, local =
not replicated over the network).
If you’re packaging a JVM app and your conveyor.compatibility-level
key is 8 or higher the system-wide
temp directory will be devirtualized automatically. This is to avoid a buggy interaction between UNIX domain sockets,
the Java 19+ networking stack and Windows.
A couple of other enhancements for Windows development:
- Some frameworks or APIs need you to know your “app user model ID” (AUMID). You can now compute this by running
conveyor make app-user-model-id
. - We’ve refreshed the AppX Manifest schemas bundled with the tool.
What’s that about? One of Conveyor’s core design decisions is to let you control OS specific details as well as providing high level abstractions - you should never have to choose between convenience and control. As a part of that we let you specify fragments of AppX Manifest XML or even the whole file. That lets you get any Windows-specific integration you need. Because the format is so complex we also bundle the XSD validation schemas and run them, ensuring that any mistakes are picked up at package build time rather than install time. Our refresh picks up recently added features and namespaces.
Usability improvements
In every release we review the support tickets filed over that period and make product changes to fix them, like by checking for common mistakes and printing warnings. You’ll see an example of that if you accidentally write config like this:
app {
app.foo.bar = true
}
That particular copy/paste mistake defines an app
object inside the top level app
object and is already checked for
before the March update. In this release:
- Conveyor checks that your chosen download site server supports HTTP Range requests. This is required for installation on Windows and resumption of incomplete update downloads on macOS.
- If you don’t specify the main class of your JVM app then Conveyor discovers it automatically. That is convenient but can be confusing if you think you’re specifying it, got that wrong and then Conveyor picks up an unrelated entry point from a library. We now print a warning when the main class was inferred.
We’ll keep automating the experience gained from support requests over time.
Wrap up
Last but not least we’ve added support for new Electron and JVM versions, and there are a variety of bug fixes. We hope you enjoy the upgrade!