Skip to content

Packaging

Derek Yang edited this page Oct 6, 2026 · 5 revisions

FluentDL releases come in two forms:

  • Store: one unsigned MSIX per architecture, uploaded to Partner Center by hand. It depends on the Windows App SDK runtime, which the Store installs along with FluentDL.
  • Sideload: one ZIP per architecture for GitHub Releases. It holds an MSIX that includes the Windows App SDK, plus an installer script.

Both forms include .NET, so users never install it separately.

The packaging script lives in FluentDL/PackageSelect. BuildPackages.cs is a C# file that dotnet run compiles and runs without a project file, and build_packages.cmd starts it for you.

Release with GitHub Actions

The Release workflow runs the same script on GitHub.

  1. Set the new version in FluentDL/Package.appxmanifest and FluentDL/app.manifest, and commit it to master.

  2. Tag that commit with the version and push the tag. You can also start the workflow from the Actions tab with Run workflow.

    git tag 3.9.0.0
    git push origin 3.9.0.0
  3. The workflow stops if the version doesn't match both manifests. Otherwise it builds the packages, installs and starts each sideload package on an x64 and an Arm64 runner, and creates a draft release with the two ZIPs.

  4. For versions ending in .0, download FluentDL_<version>_x64.msix and FluentDL_<version>_arm64.msix from Artifacts at the bottom of the run's page, and upload them in Partner Center.

  5. Edit the draft's notes under Releases and publish it. Nothing is public until then.

If a run fails, fix the problem on master, then move the tag to the fixed commit with git push origin :refs/tags/3.9.0.0, git tag -f 3.9.0.0 and git push origin 3.9.0.0.

Every pull request and push to master also builds test ZIPs, which stay under Artifacts on the CI run's page for 14 days. The rest of this page covers building packages on your PC.

Requirements

  • The .NET 10 SDK or later. It runs the script, and the script builds the packages with dotnet msbuild.
  • Visual Studio's Windows application development workload, which you already need to build FluentDL.

Build packages

Double-click FluentDL\PackageSelect\build_packages.cmd, or run it from a terminal without options. It asks for:

  1. The channel: All, Store or Sideload.
  2. The architecture: All, x64 or arm64.
  3. The version. It suggests the version in Package.appxmanifest.
  4. Whether to copy sideload builds to the Windows Sandbox share, when you build sideload packages.
  5. Whether to replace files from an earlier build, when any exist.

It then shows the matching command and builds once you confirm. The window stays open at the end so you can read the result.

The first run takes about 20 seconds to compile the script, and later runs reuse that build. Each package takes about a minute. The console only shows errors, and the full build output goes to a log file.

Building all four packages produces:

artifacts\3.8.0.0\
    Store\x64\FluentDL_3.8.0.0_x64.msix
    Store\arm64\FluentDL_3.8.0.0_arm64.msix
    Sideload\FluentDL_3.8.0.0_x64.zip
    Sideload\FluentDL_3.8.0.0_arm64.zip
    logs\

Store versions must end in .0, because the Store reserves the last number. Each sideload ZIP holds a FluentDL_<version>_<architecture> folder with the MSIX, install_fluentdl.cmd and install_fluentdl.ps1.

To skip the prompts, pass options. From the FluentDL project folder:

.\PackageSelect\build_packages.cmd --version 3.8.0.0
.\PackageSelect\build_packages.cmd --version 3.8.0.0 --channel Sideload --architecture x64

With options, the launcher doesn't pause at the end. It won't replace files from an earlier run unless you add --overwrite, and it leaves other files in the output folder alone. Run build_packages.cmd --help for every option.

The launcher runs dotnet run --file BuildPackages.cs -- <options>. If you run that command yourself from the FluentDL folder, keep --file. Without it, dotnet run sees FluentDL.csproj and builds and runs FluentDL instead.

Options

Each option can also come from an environment variable. A command-line option wins over its variable, and a blank variable counts as unset.

Option Environment variable When unset
--output FLUENTDL_PACKAGE_OUTPUT artifacts in the project folder
--sandbox-share FLUENTDL_SANDBOX_SHARE No sandbox copy
--msbuild FLUENTDL_MSBUILD dotnet msbuild

--no-sandbox skips the sandbox copy even when FLUENTDL_SANDBOX_SHARE is set. If you set a path, it has to exist. The script stops with an error instead of falling back to the default.

To keep a variable for your Windows account rather than one terminal:

[Environment]::SetEnvironmentVariable('FLUENTDL_SANDBOX_SHARE', 'C:\path\to\SandboxShare', 'User')

Restart terminals and Visual Studio afterwards so they pick it up.

Test a sideload package in Windows Sandbox

  1. Set FLUENTDL_SANDBOX_SHARE to a folder that your Windows Sandbox configuration maps into the sandbox.
  2. Build a sideload package. The script copies its unzipped folder into the share. Store packages and ZIPs aren't copied.
  3. In the sandbox, open that folder and run install_fluentdl.cmd.

The installer asks for administrator rights, because Windows only installs unsigned packages from an elevated prompt. Accept the prompt with the same Windows account. The installer then installs the MSIX and opens FluentDL.

Building ARM64 packages on an x64 PC doesn't test whether they run. Test them on ARM hardware.

What the script does

  • It writes temporary copies of store.appxmanifest.txt or sideload.appxmanifest.txt, and of app.manifest, with the requested version. The two manifest templates hold different package identities. The sideload publisher ends in the OID that Windows requires before it installs an unsigned package.
  • It builds FluentDL.csproj in Release mode, passing the packaging settings to MSBuild. Build files go to obj\Packaging and bin\Packaging. It doesn't change FluentDL.csproj or Package.appxmanifest.
  • It checks each MSIX for the expected identity, version and architecture, that it's unsigned, and that every file in it matches its checksum. Only Store packages may depend on the Windows App SDK runtime.
  • If any build fails, it copies nothing to the output folder, and existing release files stay as they were. Build logs are in artifacts\<version>\logs. They contain local paths, so read them before sharing.
  • Don't run two builds of the same package at once.
  • FluentDL.csproj excludes the PackageSelect folder from compilation, so the script never ends up inside the app.

Release builds include portable PDB files, which aren't in the ZIP. Keep the PDBs for each released version and architecture before rebuilding. See Logging and diagnostics for how to use them.

Clone this wiki locally