StageKit.Fallout 0.4.0

dotnet add package StageKit.Fallout --version 0.4.0
                    
NuGet\Install-Package StageKit.Fallout -Version 0.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="StageKit.Fallout" Version="0.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="StageKit.Fallout" Version="0.4.0" />
                    
Directory.Packages.props
<PackageReference Include="StageKit.Fallout" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add StageKit.Fallout --version 0.4.0
                    
#r "nuget: StageKit.Fallout, 0.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package StageKit.Fallout@0.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=StageKit.Fallout&version=0.4.0
                    
Install as a Cake Addin
#tool nuget:?package=StageKit.Fallout&version=0.4.0
                    
Install as a Cake Tool

StageKit.Fallout

Logo

License GitHub repo size Code size Nuget GitHub Sponsors

StageKit.Fallout is the reusable build-pipeline library behind StageKit's release process. It is a Fallout (NUKE-style) build that discovers the solution and main project, resolves software metadata from MSBuild properties, and exposes ready-made targets to restore, compile, run, and publish an application to every supported platform bundle.

Features

  • Solution and main-project discovery, preferring .slnx over .sln
  • Software metadata (name, company, RDNS, version, license, repository URL, tags) resolved from the main project's MSBuild properties
  • Ready-made Print, Clean, Restore, Compile, Run, Publish, GenerateInstallScript, and GenerateWindowsWixInstaller targets
  • Self-contained publish by default, with optional ReadyToRun and framework-dependent deployment
  • Bundle creation: portable zip, .NET single-file, WiX installer, macOS .app/DMG/PKG, Linux AppImage, Flatpak, Debian, RPM, Arch Linux, and Snap packages
  • Unified cross-platform file associations via FileAssociation and FileAssociations
  • Multi-architecture macOS bundles (osx-x64 + osx-arm64 in one .app)
  • Versioned build runtime manifest emitted with each distributable for diagnostics and release tooling
  • Release notes extracted from the top CHANGELOG.md section
  • virtual members and callbacks throughout so a derived build can override any step

Requirements

  • .NET 10 SDK
  • Fallout.Common and Fallout.Utilities 10.4.0
  • The fallout global tool, pinned in .config/dotnet-tools.json

Native packaging tools

The native Linux package tools are only required when the corresponding value is included in PackagingTypes:

Packaging type Required tool Debian/Ubuntu package Fedora package Arch package
LinuxFlatpak flatpak, flatpak-builder flatpak flatpak-builder flatpak flatpak-builder flatpak flatpak-builder
LinuxSnap snapcraft Snap package (snapd), then Snapcraft Snap package (snapd), then Snapcraft AUR snapd, then Snapcraft
LinuxDeb dpkg-deb dpkg-dev dpkg dpkg
LinuxRpm rpmbuild rpm rpm-build rpm
LinuxArchPackage makepkg, pacman, tar, bsdtar, fakeroot, zstd makepkg pacman-package-manager fakeroot zstd libarchive-tools Arch Linux host/container with base-devel base-devel

Install the tools for a Debian or Ubuntu build host with:

sudo apt update
sudo apt install -y flatpak flatpak-builder dpkg-dev rpm makepkg pacman-package-manager fakeroot zstd libarchive-tools snapd
sudo snap install snapcraft --classic

Install the tools for a Fedora build host with:

sudo dnf install -y flatpak flatpak-builder dpkg rpm-build snapd
sudo systemctl enable --now snapd.socket
sudo snap install snapcraft --classic

Build Arch packages on Arch Linux (or an Arch Linux container) with:

sudo pacman -Syu --needed base-devel flatpak flatpak-builder dpkg rpm

For Snap builds on Arch, install snapd from the AUR, enable its socket, and then install Snapcraft:

yay -S snapd
sudo systemctl enable --now snapd.socket
sudo snap install snapcraft --classic

Flatpak also needs the runtime and SDK selected by LinuxAppBundleOptions (defaults: org.freedesktop.Platform, 25.08, and org.freedesktop.Sdk). Configure Flathub and install the defaults with:

flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user -y flathub org.freedesktop.Platform//25.08 org.freedesktop.Sdk//25.08

Fallout invokes Snapcraft with --destructive-mode, which is suitable for an isolated CI runner and does not require configuring an LXD or Multipass provider.

LinuxAppImage downloads and caches the matching appimagetool automatically. FUSE 2 is optional; when it is not available, Fallout extracts the AppImage tool before running it. macOS DMG/PKG creation uses the platform tools hdiutil and pkgbuild, and Windows Installer creation requires a WiX .wixproj and a Windows host.

How it runs

build.ps1 / build.sh
  └── bootstrap the .NET SDK if absent, then `dotnet tool restore`
      └── dotnet fallout <target> [parameters]
          └── compiles and runs builds/build/build.csproj  (configured by .fallout/parameters.json)
              └── Build : StageKitBuild

.fallout/parameters.json points Fallout at the solution and the build project:

{
  "$schema": "build.schema.json",
  "Solution": "StageKit.slnx",
  "BuildProjectFile": "builds/build/build.csproj"
}

Run a target:

./build.ps1 Print
./build.ps1 Compile
./build.ps1 Publish
./build.ps1 GenerateInstallScript
./build.sh Publish

Targets

Target Depends on Description
Print Logs every public build variable, including resolved metadata and bundle options. Useful for diagnosing configuration.
Clean runs before Restore dotnet clean plus deletion of ArtifactsDirectory.
Restore dotnet restore on MainProject.
Compile Restore dotnet build on MainProject. Default target.
Run Compile dotnet run on MainProject with --no-build --no-restore.
Publish Restore Publishes every runtime identifier in RIds and creates the packaging formats selected by PackagingTypes.
GenerateInstallScript Generates Bash and Windows PowerShell install/uninstall scripts for compatible GitHub release assets.
GenerateWindowsWixInstaller Scaffolds builds/<SoftwareName>.WixInstaller, the WiX project Publish builds into an MSI. Fails when it exists.

DependOnTargets lets a derived build inject extra targets into Compile, Run, and Publish.

Parameters

Declared with Fallout's [Parameter] attribute, so each can be supplied on the command line or through the environment.

Parameter Default Description
Configuration Release Debug or Release.
PackagingTypes [Portable] Unique packaging formats to create; use an empty array to skip packaging.
RIds win-x64 win-arm64 osx-x64 osx-arm64 linux-x64 linux-arm64 Runtime identifiers to publish.
FrameworkDependent false Publish framework-dependent applications instead of self-contained applications.
PublishMultiArch false Create one macOS app bundle containing both x64 and arm64 executables. Requires both macOS RIDs.
DeletePublishDirectories false Delete raw publish directories after publishing.
ReadyToRun false Publish ReadyToRun (R2R) compiled applications.
PublishTrimmed false Publish trimmed applications.
AppImageCompression null Squashfs compression passed to appimagetool. Use 'default' for appimagetool default.

Software metadata

Metadata is read from the main project's evaluated MSBuild properties, so the build never duplicates values that already live in Directory.Build.props or the project file:

Build property MSBuild source
ArtifactsDirectory ArtifactsPath
SolutionName Solution name, falling back through Product, AssemblyName, and SolutionName
SoftwareName SoftwareName, then RepositoryName, then SolutionName; used for product and artifact naming
SoftwareExecutableName AssemblyName, falling back to the main project name; used to locate the published executable
SoftwareCompany / SoftwareCompanyRdns Company / CompanyRDNS
SoftwareRDNS <CompanyRDNS>.<SoftwareName>
SoftwareAuthors Authors
SoftwareSummary Summary, falling back to Description
SoftwareDescription Description
SoftwareVersion Version, with a trailing -dev suffix removed
SoftwareCopyright Copyright
SoftwareLicense PackageLicenseExpression
SoftwareRepositoryUrl RepositoryUrl
SoftwarePackageTags / SoftwarePackageTagsList PackageTags
BuildRuntimeManifestFileName BuildRuntimeManifestFileName, defaulting to build-runtime.json
ContextMenuOpenWithFileAssociations ContextMenuOpenWithFileAssociations

MainProject is the last runnable, non-excluded project in solution order. ExcludedProjectNameTokens disqualifies candidates by name token (test, demo, build, sample, fake, docs, and more). Override MainProject directly when the solution holds several candidates.

Publishing

Each runtime identifier is published self-contained with ReadyToRun into artifacts/publish/<AssetName>/ by default. Set FrameworkDependent to true when the target system supplies the matching .NET runtime. The default asset name is:

<SoftwareName>_<runtime-identifier>_v<SoftwareVersion>

Override it through the AssetName callback. Bundles are then created from that output:

SoftwareName does not need to match the executable file name. Fallout resolves the executable stem from the main project's evaluated AssemblyName through SoftwareExecutableName, adding .exe only for Windows RIDs. The default macOS and Linux bundle launchers use the same executable name while retaining SoftwareName for display and artifact names. Windows installer builds receive both values as ApplicationName and ApplicationExecutableName, so WiX metadata, shortcuts, and install folders remain product-named while the payload points to the actual executable.

Bundle ApplicationPackagingType value Host requirement Output
Portable zip Portable Any <asset>.zip (skipped for macOS RIDs when MacOSAppBundle is also enabled)
.NET single-file DotNetSingleFile Any Single executable copied beside the publish folder
Windows installer WindowsInstaller Windows host and a WiX .wixproj in the solution .msi / .exe produced by the installer project
macOS app bundle MacOSAppBundle Unix host <asset>.app
macOS disk image MacOSDmg macOS host with hdiutil <asset>.dmg
macOS installer MacOSPkg macOS host with pkgbuild <asset>.pkg
Linux AppImage LinuxAppImage Linux host <asset>.AppImage
Linux Flatpak LinuxFlatpak Linux host with flatpak-builder <asset>.flatpak
Linux Snap LinuxSnap Linux host with snapcraft <asset>.snap
Debian Deb LinuxDeb Linux host with dpkg-deb <asset>.deb
RHEL RPM LinuxRpm Linux host with rpmbuild <asset>.rpm
Arch package LinuxArchPackage Linux host with makepkg <asset>.pkg.tar.zst

PackagingTypes defaults to [Portable] in StageKitBuild. Derived builds select multiple formats with an array:

PackagingTypes =
[
    ApplicationPackagingType.Portable,
    ApplicationPackagingType.LinuxArchPackage
];

Duplicate values and None are removed while preserving selection order. Formats whose host requirement is unmet are skipped with a warning rather than failing the build. Set PackagingTypes to [] to publish runtime outputs without creating packages.

Cross-platform file associations

Unified file associations can be defined once in StageKitBuild.FileAssociations and automatically propagate to every supported platform bundle format:

FileAssociations =
[
    new FileAssociation(".stg", "StageKit File", "application/x-stagekit")
];
  • Windows WiX Installer: Automatically registers Windows Explorer context menu / "Open with" handlers for each extension.
  • macOS Bundles (.app): Automatically configures CFBundleDocumentTypes entries in Info.plist.
  • Linux Bundles: Automatically populates MimeType associations in .desktop files, adds %F arguments to Exec, and includes AppStream mediatype metadata.

Windows installer options & WiX project

Publish builds every WiX project in the solution when PackagingTypes contains WindowsInstaller. Run GenerateWindowsWixInstaller once to scaffold that project:

./build.ps1 GenerateWindowsWixInstaller

It writes builds/<SoftwareName>.WixInstaller with the project file, Package.wxs, Strings.en-us.wxl, a readme, a placeholder Resources/License.rtf, and placeholder Resources/InstallerBannerImage.png (493 × 58) and Resources/InstallerDialogImage.png (493 × 312) artwork. The generated wizard lets the user choose a per-user or per-machine installation and offers Start menu, desktop shortcut, and launch-after-install options. It accepts older and same-version packages as major upgrades. Every product-specific value — publish payload, application name, executable name, version, platform, and asset name — is passed by the pipeline at build time, so the project builds without editing.

Windows installer options are configured in C# via WindowsInstallerOptions on StageKitBuild:

WindowsInstallerOptions = new WindowsInstallerOptions
{
    Scope = InstallerScope.PerMachineOrUser,
    PathRegistration = PathRegistration.UserDefaultYes,
    DefaultDesktopShortcut = true,
    DefaultStartMenuShortcut = true,
    DefaultStartProgramAfterInstall = true,
    SingleFile = false
};
Installation scope

WindowsInstallerOptions.Scope uses the strongly typed InstallerScope enum:

  • InstallerScope.PerMachineOrUser: User chooses the installation scope in the wizard, defaulting to non-elevated per-user.
  • InstallerScope.PerUser: Enforces per-user installation and hides the selector.
  • InstallerScope.PerMachine: Enforces per-machine installation and hides the selector.

The scope can also be overridden when building the WiX project with -p:InstallerScope=perUser or -p:InstallerScope=perMachine. The selector is disabled while a previous installation is detected, because Windows Installer keeps a product in the context it was first installed in. A silent installation of a perMachineOrUser package is per-user unless it is invoked with msiexec /i <package>.msi ALLUSERS=1 /qn.

PATH registration

WindowsInstallerOptions.PathRegistration uses the strongly typed PathRegistration enum:

  • PathRegistration.None: Disables PATH registration and hides the wizard option.
  • PathRegistration.Register: Always appends the installation directory to PATH and hides the option.
  • PathRegistration.UserDefaultNo: Shows an unchecked checkbox for the user during setup.
  • PathRegistration.UserDefaultYes: Shows a checked checkbox for the user during setup.

Per-user installations update the current user's PATH, per-machine installations update the system PATH, and uninstall removes the installer-managed entry. Which of the two applies follows the installation context Windows Installer resolved, not the scope picked in the wizard, because a per-user installation cannot write the system PATH. The entry is the installation directory as Windows Installer resolves it, so it carries a trailing separator.

Set WindowsAuthenticodeCertificateThumbprint to a SHA-1 certificate thumbprint to sign the staged application executable and final MSI. Fallout forwards WindowsInstallerOptions.AuthenticodeTimestampUrl (defaulting to DigiCert's RFC 3161 service) and WindowsInstallerOptions.SignToolPath (defaulting to signtool.exe) to the WiX build. The certificate must be available in the current user's certificate store; leaving the thumbprint blank disables signing. Every .exe and .dll in the payload is signed, which for a self-contained publish replaces the signatures the .NET runtime binaries ship with and costs one timestamped signtool invocation per file; redefine the InstallerPayloadToSign item in the WiX project to narrow that set.

A full uninstall deletes the installer's registry key outright, so it leaves nothing behind. Remembered preferences — installation directory, scope, shortcut and PATH choices — still survive upgrades and repairs, because AppSearch captures them into properties long before RemoveExistingProducts removes the previous version.

Two upgrade codes are generated, one per platform, and written into the project. They must stay stable: changing one makes Windows treat later installers as a different product instead of an upgrade. For that reason the target refuses to overwrite an existing project and fails when builds/<SoftwareName>.WixInstaller already exists and is not empty. Delete the directory to regenerate it, and add the project to the solution so InstallerProjects finds it.

Override WindowsWixInstallerProjectName, WindowsWixInstallerDirectory, WindowsWixInstallerProjectFile, CreateWindowsWixInstallerLicense(), or CreateWindowsWixInstallerUpgradeCode() in a derived build to change the destination, scaffold the real license, or supply pre-agreed upgrade codes.

Installation script

Run GenerateInstallScript to create scripts/install-<software-name>.sh, scripts/uninstall-<software-name>.sh, scripts/install-<software-name>.ps1, and scripts/uninstall-<software-name>.ps1. The target is independent of Publish, so it can describe packages produced by separate Windows, Linux, and macOS runners without trying to build them locally. A script is omitted when none of its supported formats are selected. Every installer run prints a command header, its help command shows detailed usage, list shows all published GitHub release versions, and list-changelog shows GitHub release notes for up to 20 versions by default. Pass a different positive limit when needed. Install the latest version or select an older release to downgrade:

./scripts/install-myapp.sh
./scripts/install-myapp.sh install v1.2.3
./scripts/install-myapp.sh --version 1.2.3
./scripts/install-myapp.sh --list
./scripts/install-myapp.sh --list-changelog
./scripts/install-myapp.sh --list-changelog 5
./scripts/install-myapp.sh --portable
./scripts/install-myapp.sh --portable /home/user/apps
./scripts/install-myapp.sh help

--portable forces selection of the Linux Portable ZIP and extracts it to <current-directory>/<software-name>. Passing a path extracts to <path>/<software-name> instead. This extraction mode does not create a launcher in ~/.local/bin.

The generated Bash uninstaller checks every supported package format and removes all installations it detects through the appropriate system tool. It covers user and system Flatpak installations, Snap, DEB, RPM, Arch Linux, AppImage, single-file, Portable, and macOS application/PKG installations. Use the matching portable parent path to also remove a custom extraction:

./scripts/uninstall-myapp.sh
./scripts/uninstall-myapp.sh --portable /home/user/apps
.\scripts\install-myapp.ps1
.\scripts\install-myapp.ps1 install v1.2.3
.\scripts\install-myapp.ps1 -Version 1.2.3
.\scripts\install-myapp.ps1 -List
.\scripts\install-myapp.ps1 -ListChangelog
.\scripts\install-myapp.ps1 -ListChangelog -ChangelogLimit 5
.\scripts\install-myapp.ps1 -Help
.\scripts\uninstall-myapp.ps1

The Bash list-changelog command uses jq when available and otherwise falls back to python3 to decode GitHub's release-note JSON.

Only formats present in PackagingTypes are emitted. Their priority follows the insertion order of ApplicationPackagingInfo.KnownPackagingTypes. Linux first tries the package native to the detected distribution (DEB, RPM, or Arch), followed by AppImage, Flatpak, Snap, .NET single-file, and finally Portable. macOS tries the app-bundle archive, followed by PKG and DMG. Incompatible formats are skipped and the next selected format is tried. The release asset must contain Fallout's runtime identifier (linux-x64, linux-arm64, osx-x64, osx-arm64, or osx-multiarch) and use the standard extension for its packaging type. This is automatic with the default AssetName callback.

Standalone assets retain the case of SoftwareName when installed: AppImages use ~/Applications/<software-name>.AppImage, Linux .NET single-file executables use ~/.local/bin/<software-name>.bin, and Windows .NET single-file executables use <software-name>.exe.

Windows PowerShell first tries a Windows installer (.msi, then .exe), followed by the .NET single-file executable and finally the Portable zip. Single-file and Portable packages install under %LOCALAPPDATA%\Programs\<package> and add the executable directory to the current user's PATH. MSI packages run passively and request elevation when needed; whether an MSI permits installing an older version is controlled by that installer project. Missing release versions and GitHub request failures are reported as concise script errors instead of raw PowerShell exceptions. Set WindowsInstallScriptWinGetPackageId to an exact WinGet package identifier to make the Windows script try a silent WinGet install first. If WinGet is unavailable or returns an error, the script falls back to its normal GitHub release asset selection and installation. Explicit versions are passed to WinGet without a leading v and use its force option. The generated Windows uninstaller tries that exact WinGet package ID, then exact application-name entries in the Windows uninstall registry, and finally removes StageKit's known %LOCALAPPDATA%\Programs\<package> directory and corresponding user PATH entries. It continues checking the other installation forms if one removal fails.

Explicit version selection accepts tags with or without the leading v and enables package-manager downgrade options for DEB and RPM installation. Arch, Flatpak, Snap, portable, and application-bundle formats replace or update the currently installed package with the selected release according to their native tool behavior.

The repository metadata must identify GitHub through an HTTPS URL such as https://github.com/owner/repository or an SSH URL such as git@github.com:owner/repository.git. Override InstallScriptFile, UninstallScriptFile, WindowsInstallScriptFile, WindowsUninstallScriptFile, CreateInstallScript(), CreateUninstallScript(), CreateWindowsInstallScript(), CreateWindowsUninstallScript(), or ExecuteGenerateInstallScript() in a derived build to customize the output paths, contents, or write step.

DMG and PKG creation stage and sign the same .app layout used by MacOSAppBundle. DMG output contains the application bundle alone, while PKG output installs the app directly in /Applications. The application bundle is passed to hdiutil create -srcfolder directly, and the DMG deliberately carries no /Applications drag-and-drop symlink: hdiutil follows such a symlink while scanning the source tree, walks the whole host /Applications directory, and gets killed with exit code 137 on GitHub-hosted macOS runners. Native macOS packages are created before the application ZIP to keep peak packaging memory lower. With PublishMultiArch, both native formats contain the combined osx-x64 and osx-arm64 app. Avalonia applications should also set Application.Name in App.axaml to the same value as SoftwareName; otherwise, Avalonia may replace the macOS menu title at runtime with its Avalonia Application fallback despite the generated CFBundleName and CFBundleDisplayName values.

Debian, RPM, and Arch Linux payloads install the application under /usr/lib/<package> and a launcher under /usr/bin/<package>. When selecting LinuxDeb, set LinuxAppBundleOptions.DebPackageMaintainer to Full Name <email@example.com>. Snap defaults to the core24 base, strict confinement, common desktop interfaces, and the libicu74 stage package required by self-contained .NET apps; customize DeveloperId, SnapBase, SnapConfinement, SnapPlugs, or SnapStagePackages through LinuxAppBundleOptions. DeveloperId defaults to CompanyRDNS and identifies the publishing organization in AppStream metadata. Stage-package names are base-specific, so update SnapStagePackages when changing SnapBase. Native package tools and the selected Flatpak/Snap runtime bases must already be available on the build host. Debian payloads are staged in the operating system's temporary directory so dpkg-deb receives valid Unix permissions even when the repository is on a Windows-mounted WSL path such as /mnt/c or /mnt/d.

Set LinuxAppBundleOptions.FlatpakAllowHostCommandExecution to true when a Flatpak application must use flatpak-spawn --host. This adds the broad --talk-name=org.freedesktop.Flatpak sandbox permission and is disabled by default; prefer a narrower portal operation whenever one is available. StageKit.Updatum uses this host bridge automatically for Flatpak package installation and stages its downloaded bundle in the host-visible application cache.

Icons are read from MediaDirectory (media/ by default): <SoftwareName>.icns for macOS and <SoftwareName>.svg for Linux. Override LinuxIconFile to use a .png icon; both SVG and PNG are accepted. SVG icons are installed in the scalable hicolor directory, while PNG icons are installed in 256x256/apps. AppImage creation downloads and caches appimagetool for the host architecture; when FUSE 2 is unavailable the tool is extracted before use.

PublishCleanupExtensions (default wixpdb) removes leftover files from the publish directory after a successful run.

Unix file permissions

Use UnixFilePermissions to apply chmod modes to files in every Unix-like runtime's published output. Keys must be nonblank relative paths that resolve beneath the runtime publish directory; absolute paths, traversal paths, missing files, and reparse-point escapes are rejected. Values use the mode syntax accepted by Unix chmod. Windows runtime publishes ignore this configuration, and permission changes are a no-op when cross-publishing from a Windows host.

public Build()
{
    UnixFilePermissions["tools/helper"] = "755";
    UnixFilePermissions["scripts/start.sh"] = "u+x";
}

Build runtime manifest

Each distributable receives a BuildRuntime JSON manifest named by BuildRuntimeManifestFileName. Portable archives, installer payloads, macOS bundles, and AppImages stage it beside the application payload; single-file publishing embeds it as bundled content. StageKit.Runtime automatically exposes the default build-runtime.json file through BuildRuntime.Instance; use BuildRuntime.TryLoad(...) when this Fallout file name is customized.

The schema is versioned independently through SchemaVersion so consumers can reject or migrate future layouts:

{
  "SchemaVersion": 1,
  "Runtime": "linux-x64",
  "IsBundle": true,
  "PackagingType": "LinuxAppImage",
  "BuildDateTimeUtc": "2026-08-28T12:34:56.789Z",
  "BuildOSDescription": "Ubuntu 24.04 LTS",
  "BuildVersion": "1.0.0"
}

Release notes

Publish extracts the top section of ChangelogFile (CHANGELOG.md) into ReleaseNotesFile (RELEASE_NOTES.md) before publishing, ready for a release job to consume.

Customizing the build

Derive from StageKitBuild in the build entry project:

using Serilog;
using StageKit.Fallout;

internal class Build : StageKitBuild
{
    public Build()
    {
        BeforePublishRid = context =>
            Log.Information("Publishing {Rid} to {Path}", context.RuntimeIdentifier, context.PublishPath);

        // Allow a demo project to be detected as the MainProject.
        ExcludedProjectNameTokens.Remove("demo");
    }

    public override string SoftwareName => MainProject.Name;

    protected override LinuxAppBundleOptions CreateLinuxAppBundleOptions()
    {
        var options = base.CreateLinuxAppBundleOptions();
        options.Categories = ["Development"];
        options.AppRunScriptBeforeExec = "echo 'Starting...'";
        return options;
    }

    public new static int Main() => Execute<Build>(x => x.Compile);
}

Extension points

Member Purpose
SoftwareName, SoftwareExecutableName, SoftwareVersion, MainProject, Solution virtual — override when auto-detection is wrong
ExcludedProjectNameTokens Mutable token list controlling MainProject detection
BeforePublishRid / AfterPublishRid Action<PublishRidContext> hooks around each runtime publish
AssetName Func<PublishRidContext, string> returning the base artifact name (simple file name, no directory or extension)
ConfigurePublishRid Func<DotNetPublishSettings, PublishRidContext, DotNetPublishSettings> to adjust publish settings per RID
CreateMacAppBundleOptions() / CreateLinuxAppBundleOptions() / CreateWindowsInstallerOptions() Lazily resolved bundle and installer options (Info.plist, .desktop, WiX MSI)
ConfigureWindowsInstallerBuildSettings(...) Adjusts the MSBuild settings passed to each WiX installer project
PackagingTypes, PublishCleanupExtensions, RIds Protected setters for build-wide publish configuration
MediaDirectory, WindowsIconFile, MacOSIconFile, LinuxIconFile, ChangelogFile, ReleaseNotesFile virtual path overrides

Nearly every publish and bundle step (CreatePublishSettings, PublishRuntime, CreateBundles, CreatePortableZip, CreateMacOSApp, CreateLinuxAppImage, CreateWindowsInstallers, …) is protected virtual and can be replaced.

License

StageKit.Fallout is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.4.0 0 2026/9/14
0.3.8 64 2026/9/11
0.3.7 57 2026/9/11
0.3.6 72 2026/9/10
0.3.5 52 2026/9/10
0.3.4 52 2026/9/9
0.3.3 45 2026/9/8
0.3.2 101 2026/9/5
0.3.1 94 2026/9/5
0.3.0 100 2026/9/3