kuiperzone / PupNet-Deploy

PupNet Deploy is a cross-platform deployment utility which packages your .NET project as a ready-to-ship installation file in a single step.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PupNet Deploy - Publish & Package for .NET

PupNet Deploy is a cross-platform deployment utility which packages your .NET project as a ready-to-ship installation file in a single step.

If you like this project, don't forget to click star and share.

CONTENTS

INTRODUCTION

It has been possible to cross-compile console C# applications for sometime now. More recently, the cross-platform Avalonia replacement for WPF allows fully-featured GUI applications to target a range of platforms, including: Linux, Windows, MacOS and Android.

Now, PupNet Deploy allows you to ship your dotnet application as:

  • AppImage for Linux
  • Setup File for Windows
  • Flatpak for Linux
  • Debian Binary Package
  • RPM Binary Package
  • Plain old Zip

To create an installation file, you fill out the parameters in a simple pupnet.conf file and, from within your project, run a command like so:

pupnet --runtime linux-x64 --kind appimage

In this case, PupNet calls dotnet publish on your project and generates a distributable AppImage file fo use on Linux systems. Additionally, you may optionally provide .desktop and AppStream metadata files. There is no need to write complex build-specific manifests, RPM spec or Debian control files. You need only supply your deployment configuration once as a single pupnet.conf file, and PupNet takes care of the underlying build-specific tasks.

Likewise, to package the same project for Windows:

pupnet -r win-x64 -k setup

PupNet has good support for internationalization, desktop icons, publisher metadata and custom build operations. Although developed for .NET, it is also possible to use it to deploy C++ and other kinds of applications.

The output of PupNet is a distributable file, such as an AppImage, flatpak or Windows Setup.exe file -- it does not auto-submit your project to repositories. Note also that, in order to build a Linux deployment, the build system must be a Linux box and, likewise to build a Windows Setup file, a Windows system (virtual machines are handy).

However, it is possible to build a Debian package on an RPM machine, and viceversa.

General Principles

Single App per Install Package

It is assumed that you are building a deployment package containing a single application. AppImages also work this way and, from .NET7 onward, it is no longer possible to publish a dotnet solution containing multiple projects.

This may be something investigated in the future but, for the moment, PupNet is not suitable for deploying a suit of applications as a single package.

Read-only Access to Installation

As a general principle when deploying your software, it should be assumed that your application has read-only access to its installation folder. Your application should use the Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData location or other suitable special folder to write data.

INSTALL & PREREQUISITES

To install as a dotnet tool:

dotnet tool install -g KuiperZone.PupNet

Currently, the "PupNet tool" targets .NET8 LTS (this does not restrict the dotnet version of your own projects). The last version of PupNet built against .NET6 was 1.7.1.

Alternatively, for self-contained installers:

DOWNLOAD & INSTALL

If you are using the AppImage deployment of PupNet, add it to your path and consider renaming the AppImage file to pupnet so that the instructions below will match your system.

AppImage Out of the Box

Out of the box, PupNet can create AppImages on Linux and Zip files on all platforms. There is no need to install any AppImage tools therefore. In order to build other deployments, however, you must first install the appropriate third-party builder tool against which PupNet will call.

Flatpaks on Linux

PupNet requires flatpak and flatpak-builder. It will also be necessary to install a flatpak platform SDK and runtime. As appropriate, use:

sudo dnf install flatpak flatpak-builder

or:

sudo apt install flatpak flatpak-builder

And then use flatpak to install:

sudo flatpak install flathub org.freedesktop.Platform//23.08 org.freedesktop.Sdk//23.08

Here, the version number (23.08) was the latest at the time of writing, but will be subject to update. See Flatpak Available Runtimes.

Debian Packages on Linux

PupNet requires dpkg-deb. So, as appropriate:

sudo apt install dpkg

or:

sudo dnf install dpkg

It is possible to build Debian packages using dpkg-deb on an RPM based system. However, it is not recommended to test install a Debian package on an RPM machine (use a virtual machines to test it).

RPM Packages on Linux

PupNet requires rpmbuild. As appropriate:

sudo dnf install rpmdevtools

or:

sudo apt install rpm

It is possible to build RPM packages using rpmbuild on a Debian system. However, as above, it is not recommended to test install an RPM package on a Debian machine (use a virtual machines to test it).

Setup Files on Windows

PupNet leverages InnoSetup on Windows. Download and install it.

It will also be necessary to manually add the InnoSetup location to the user's PATH variable so that PupNet can call the iscc compiler. See screenshot below below:

PUPNET CONFIGURATION

Hello World for PupNet is a demonstration project for PupNet Deploy. It will be instructive to discuss the major configuration elements with reference to this simple project, as it demonstrates all the major features of building distributable packages.

The Hello World project lives in a separate git repo of its own:

Head over to this project in a different browser tab, or download it to your local drive.

Now, take a look at the HelloWorld.pupnet.conf in the root of the project.

This is a simple ini file in which the deployment project is configured. Where local paths are given, they are local to the .conf file, rather than your current working directory. Always use the forward-slash '/' as a path separator for cross-platform compatibility.

You will see that each parameter is documented. However, we will discuss key properties and issues below.

Desktop File

Note the DesktopFile parameter which provides a path to a Linux .desktop file. If you leave it blank, one will be generated automatically. In the Hello World demo, we have specified a file in order to show the default contents...

Open the file Deploy/app.desktop, and you will see:

[Desktop Entry]
Type=Application
Name=${APP_FRIENDLY_NAME}
Icon=${APP_ID}
Comment=${APP_SHORT_SUMMARY}
Exec=${INSTALL_EXEC}
TryExec=${INSTALL_EXEC}
NoDisplay=${DESKTOP_NODISPLAY}
X-AppImage-Integrate=${DESKTOP_INTEGRATE}
Terminal=${DESKTOP_TERMINAL}
Categories=${PRIME_CATEGORY}
MimeType=
Keywords=

Note that the contents above are entirely populated using macro variables (more below on these). However, you can easily extend this file to specify a MimeType and Keywords, as well as adding international translations and additional entries.

IMPORTANT: While you can edit this file as you wish, the file must contain the line below with its macro:

Exec=${INSTALL_EXEC}

Or, if you prefer:

Exec=${INSTALL_BIN}/app-name

The reason for this is that the actual path on installation will depend on the package type. You cannot hard code this here as different packages will install to different paths. It is important also that you use macros as shown with their braces, i.e. ${INSTALL_EXEC} and not $INSTALL_EXEC, as a simple search-and-replace operation is used to populate them.

In the event that you wish there be no desktop entry (i.e. a command-line application), you should declare: DesktopNoDisplay = true. The file itself is ignored for Windows Setup, although if you set DesktopNoDisplay, then no entry for your application's main executable will be added under the Windows Start Menu (i.e. synonymous behavior on Windows with that on Linux).

Hint: You can use PupNet itself to generate a Linux desktop file for a new project:

pupnet [name] --new desktop

This will create a new file for you under: name.desktop

AppStream Metadata

The MetaFile parameter specifies the path to a local AppStream metadata XML file. This applies to Linux only and is optional. This metadata is used by software centers to display information about installed applications. For detail information, see AppStream Metadata Quick Start.

If you omit the MetaFile property, no .metainfo.xml file is shipped with your application. But let's assume you wish to provide metadata, so take a look at the file provided under: Deploy/app.metainfo.xml in the Hello World demo.

Again, you will notice that macro variables are used. These are entirely optional here and simply mean that, as far as possible, deployment configuration data is specified in one place only (i.e. your pupnet.conf file). However, you may still wish to edit and extend this file to provide a screenshot, international language translations and additional information such as keywords.

IMPORTANT: Since PupNet version 1.4.0, the macros ${APPSTREAM_DESCRIPTION_XML} and ${APPSTREAM_CHANGELOG_XML} may be used to auto-populate the default application description, and change (release) information. The latter is described in more detail below under Application Versioning.

Hint: You can use PupNet itself to generate a metadata template file for a new project:

pupnet [name] --new meta

This will create a new file for you under: name.metainfo.xml

Icons

Multiple desktop icons are provided with the IconPaths parameter. You can use semi-colon as a separator, such as: IconPaths = icon1.ico;icon2.64x64.png;icon3.svg, or present them in multi-line form as shown in the Hello World demo:

IconFiles = """
    Deploy/HelloWorld.16x16.png
    Deploy/HelloWorld.24x24.png
    Deploy/HelloWorld.32x32.png
    Deploy/HelloWorld.48x48.png
    Deploy/HelloWorld.64x64.png
    Deploy/HelloWorld.svg
    Deploy/HelloWorld.ico
"""

Note the use of triple quotes here for multi-line values.

Use only the svg, png and ico file types. On Linux, svg and png files will be installed appropriately and the Windows ico file ignored. For Windows Setup packages, on the other hand, only the ico file is used, and PNG and SVG files are ignored.

IMPORTANT: It is necessary to specify the size of PNG files by embedding their size in the filename, as shown above, or simply as: name.64.png.

Dotnet Project Path

When building the deployment, PupNet first calls dotnet publish on your project. To do this, it needs to know where your project lives. In HelloWorld.pupnet.conf, you may note that file is at the solution level, but DotnetProjectPath value provides the project directory.

If your pupnet.conf files shares the same directory as your .csproj file, you may leave DotnetProjectPath empty. Otherwise use this field to specify the path to your project file or directory relative to the location of the configuration file.

Dotnet Publish Arguments

The DotnetPublishArgs parameter is used to specify values to supply to the dotnet publish call:

DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false

Do NOT include '-r' (runtime), or '-c' (configuration) here as they will be added automatically according to configuration and command line arguments.

As an absolute minimum, we always want to include --self-contained true, as this will cause dotnet not only to compile the application, but to publish all dependencies into a single directory. (From .NET8 onward you may wish to consider using Native AOT).

Application Versioning & Changelog

Application Version (AppVersionRelease)

The application version (plus release number) is specified in the pupnet.conf file, for example:

AppVersionRelease = 3.2.1[5]

Here we are using the semantic version 3.2.1 plus a "package release number" in square brackets. The release number applies specifically to the deployment package itself and is used by rpm and deb package kinds. If you omit the release number, and just give 3.2.1 for example, it defaults to 1.

If you prefer, you can override the version in the configuration file from the command line using:

pupnet --runtime linux-arm64 --kind deb --app-version 4.0.0[1]

Crucially, look again at the DotnetPublishArgs configuration value we gave above above and note ${APP_VERSION}:

DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false

Here, we can see that the version from our configuration is supplied to the build process as a variable (only the application part is supplied, i.e. 3.2.1). This is optional and you may remove it if you wish, although you will then need to specify the version both in application code and the pupnet.conf file in this case.

Changelog (AppChangeFile)

PupNet version 1.4 introduced the AppChangeFile configuration property. This gives the path to a changelog file which must use a predefined but simple format, or a README file which contains such formatted changelog information.

PupNet will parse the file and extract relevant change information. This is used to expand the ${APPSTREAM_CHANGELOG_XML} macro variable which may optionally be used within the <release> element of your AppStream metadata file. This means that lengthy version change information need only be specified once (in a changelog or README file).

Version change information is to be provided as one or more version release sections prefixed with '+' and a leading version number, and suffixed with trailing date. Subsequent change items are prefixed with '-', as shown below. Note that ';' is used as a separator.

+ VERSION;[Other fields ignored;]yyyy-MM-dd
- Change feature 3
- Change feature 4

+ VERSION;[Other fields ignored;]yyyy-MM-dd
- Change feature 1
- Change feature 2

Additional fields, between the VERSION number and trailing date, may used as you wish, i.e. to give a version title and/or maintainer contact information, as below.

+ VERSION 1.3.1; Patch Release; nobody@kuiper.zone; 2023-05-01
- Bugfix: Fix package creation when file path of contents contain spaces (enclose file path with quotes when executing chmod)

Here, the version title and contact information will be ignored and are not used in AppStream data.

It is possible for change items to span multiple lines, as follows, but a change item should not be broken with an empty line (otherwise the parser will think it is reading plain superfluous text).

The following two examples are "legal":

+ 1.3.1;2023-05-01
- Long change line
  describing feature 3
- Change feature 4


+ 1.3.1;2023-05-01

- Long change line
  describing feature 1

- Change feature 2

The following example is "illegal" and will result in version information loss:

+ 1.3.1;2023-05-01
- Long change line

  describing feature 1
- Change feature 2

The changelog parser should do a robust job at parsing version information while ignoring superfluous README text, but care should be taken to ensure that version information is correctly formatted. You may review the final AppStream metadata (after macro expansion) by using --verbose command line option when building your deployment.

Finally, it should be stressed that this feature is entirely optional. If it does not suit your project, leave AppChangeFile blank and specify version release information in your AppStream metadata file yourself (or just omit it).

Terminal vs GUI Applications

While the Hello World demo is a terminal application, it was envisaged that a typical use case for PupNet would be to deploy GUI applications built with Avalonia that are integrated with the desktop.

GUI Application

For a GUI application, you will want to ensure the following:

DesktopNoDisplay = false
DesktopTerminal = false

You may typically leave StartCommand empty, but may set it if you wish.

Terminal Application

IMPORTANT: Your terminal application will not be in the user's path by default, so note StartCommand and SetupCommandPrompt below. Note, also, that Flatpak is not suitable for command-line centric applications.

DesktopNoDisplay = true
DesktopTerminal = true
StartCommand = command-name
SetupCommandPrompt = Command Prompt

For command line only apps, you would typically set DesktopNoDisplay true, but you may give your application a desktop entry by setting it to false if you wish.

With StartCommand, you should set a simple command name for application which will be located in the user's path after installation. This will actually be realized via a tiny bash script on Linux, or bat file on Windows, which will launch your main application (the rest of your application will not be in the path). If, for example, your runnable file is something like 'Zone.Kuiper.HelloWorld', you may set StartCommand simply to 'helloworld'.

On Windows, a different approach is taken. The SetupCommandPrompt is a Windows only option which ensures that a Console entry is written to the Program Files menu (using the title you supply) which, when launched, will open a dedicated command window with your application directory in the path for the session.

Custom Post-Publish Operations

In HelloWorld.pupnet.conf, we see the lines:

DotnetPostPublish = Deploy/PostPublish.sh
DotnetPostPublishOnWindows = Deploy/PostPublish.bat

This is an advanced feature which allows you to call a command or script in order to perform additional operations after dotnet publish has been called, but prior to building the package output. The above commands are called only on their respective build systems, and should perform equivalent operation.

Such scripts may employ macro variables which are exported to the environment. The Hello World bash and batch scripts above, for example, create a subdirectory and dummy file within the application build directory, the path of which is supplied as the ${BUILD_APP_BIN} environment variable (see below for a complete reference).

Here are the contents of our example bash script:

#!/bin/bash
# This is a dummy bash script used for demonstration and test. It outputs a few variables
# and creates a dummy file in the application directory which will be detected by the program.

echo
echo "==========================="
echo "POST_PUBLISH BASH SCRIPT"
echo "==========================="
echo

# Some useful macros / environment variables
echo "BUILD_ARCH: ${BUILD_ARCH}"
echo "BUILD_TARGET: ${BUILD_TARGET}"
echo "BUILD_SHARE: ${BUILD_SHARE}"
echo "BUILD_APP_BIN: ${BUILD_APP_BIN}"
echo

# Directory and file will be detected by HelloWorld Program
echo "Do work..."
set -x #echo on
mkdir -p "${BUILD_APP_BIN}/subdir"
touch "${BUILD_APP_BIN}/subdir/file.test"
set +x #echo off

echo
echo "==========================="
echo "POST_PUBLISH END"
echo "==========================="
echo

Likewise, in the Hello World demo bat file which does the equivalent job on Windows.

Non-Dotnet Projects

Additionally, you may leverage the post-publish operations (above) to perform the actual build operation itself and populate the ${BUILD_APP_BIN} directory with the output of your build process -- whatever that may be. In principle, therefore, you could use this to package a C++ or Python application, provided that it is satisfactory that the application and all its associated libraries are contained in a single target directory.

IMPORTANT: If you do this, you will need to disable PupNet from calling dotnet publish, which can be done by setting DotnetProjectPath = NONE.

Debian & RPM Considerations

Install Location

With Debian and RPM deployments, your application will be installed to the /opt directory, rather than /usr/bin. If you set StartCommand, a tiny bash script will also be installed to /usr/bin in order to launch your application.

Dependencies

Although publishing a "self-contained" dotnet app should ideally produce a truly self-contained package, in reality it may have additional dependencies which create complexity when building RPM and Debian deployments.

Microsoft list additional dependencies for these, although note that they may also be distro specific also: https://learn.microsoft.com/en-us/dotnet/core/install/linux-scripted-manual#rpm-dependencies

From PupNet version 1.3.0 onward, the pupnet.conf file supports the ability to define such additional dependencies using the RpmRequires and DebRecommends properties. By default, they are populated with typically expected values (below), although these may be subject to change and you should review them for your application.

RpmRequires = """
    krb5-libs
    libicu
    openssl-libs
    zlib
"""

DebianRecommends = """
    libc6
    libgcc1
    libgcc-s1
    libgssapi-krb5-2
    libicu
    libssl
    libstdc++6
    libunwind
    zlib1g
"""

You should test RPM and Debian packages against your target distributions.

BUILDING THE HELLO WORLD DEMO

Hello World for PupNet can be built for all package kinds, including appimage, flatpak, deb, rpm, zip and setup for Windows.

If you wish to build and try the demo, clone or download the PupNet Hello World Project to your local drive. Ensure that you have installed the prerequisites above, or at least those you wish to use.

In the terminal, CD into the root of the project directory.

On Linux

Assuming you're on Linux, type:

pupnet --kind appimage

This will show the following information and ask for confirmation before building the deployment file.

============================================================
APPLICATION: HelloWorld 1.0.3 [1]
============================================================

AppBaseName: HelloWorld
AppId: zone.kuiper.helloworld
AppVersion: 1.0.3
PackageRelease: 1
StartCommand: helloworld [Not Supported]

============================================================
OUTPUT: APPIMAGE
============================================================

PackageKind: AppImage
Runtime: linux-x64
Arch: Auto (x86_64)
Build: Release
OutputName: HelloWorld.x86_64.AppImage
OutputDirectory: /mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/bin

============================================================
DESKTOP: app.desktop
============================================================

[Desktop Entry]
Type=Application
Name=Hello World
Icon=zone.kuiper.helloworld
Comment=A Hello World application
Exec=usr/bin/HelloWorld
TryExec=usr/bin/HelloWorld
NoDisplay=false
X-AppImage-Integrate=true
Terminal=true
Categories=Utility
MimeType=
Keywords=

============================================================
CHANGELOG: CHANGES
============================================================

+ Version 1.0.3;2023-05-04
- The pupnet.conf file upgraded to version 1.4.0
- Added ${APPSTREAM_CHANGELOG_XML} to app.metainfo.xml
- Added ${APPSTREAM_DESCRIPTION_XML} to app.metainfo.xml
- Other minor corrections and changes
- This line is deliberate test of escaping XML <>/" characters

+ Version 1.0.2;2023-04-18
- The pupnet.conf file upgraded to version 1.3.0
- Now builds using .NET6, rather than .NET7 (you can change this in csproj file if needed)
- Reinstated key-press to exit on all deployments

+ Version 1.0.1;2023-03-26
- Programs now asks for key-press only on Windows
- Reports version correctly as 1.0.1

+ Version 1.0.0;2023-03-22
- Initial release
- Reports version as "3.2.1". This was intentional at the time by way of demonstration.

============================================================
BUILD PROJECT: PupNet-HelloWorld
============================================================

dotnet publish "/mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld" -r linux-x64 -c Release -p:Version=1.0.3 --self-contained true -p:DebugType=None -p:DebugSymbols=false -o "/tmp/KuiperZone.PupNet/zone.kuiper.helloworld-linux-x64-Release-AppImage/AppDir/usr/bin"

/mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/PostPublish.sh

============================================================
BUILD PACKAGE: HelloWorld.x86_64.AppImage
============================================================

/tmp/.mount_PupNetPJRwcO/usr/bin/appimagetool-x86_64.AppImage  --runtime-file="/tmp/.mount_PupNetPJRwcO/usr/bin/runtime-x86_64" "/tmp/KuiperZone.PupNet/zone.kuiper.helloworld-linux-x64-Release-AppImage/AppDir" "/mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/bin/HelloWorld.x86_64.AppImage"

============================================================
ISSUES
============================================================

NONE

Continue? [N/y]:

This tells us that it will create a file called HelloWorld.x86_64.AppImage, under the Deploy/bin directory. Moreover, it shows the expanded contents of the desktop file, and gives the dotnet publish call it will make so that we may ensure that everything looks correct before hitting "y".

We can view more information, including the AppStream metadata contents, by using:

pupnet --kind appimage --verbose

The --verbose option is useful in other areas too, as we will see below.

On Windows

On a Windows machine with InnoSetup installed, type:

pupnet --kind setup

This will generate the file: HelloWorld.x64.exe, which may be launched to install the program.

On installation, we find we have a new Program Menu entry, as shown below. We can see that it has also included a link to our home page, which is optional.

Moreover, there is a "Command Prompt" option to launch a dedicated command window, as described above.

CREATING NEW PUPNET PROJECT FILES

If you're starting a new project, you will wish to generate a new pupnet.conf file and possibly the associated desktop and AppStream metadata files as well.

To generate a new pupnet.conf file in the current working directory:

pupnet --new conf

This will create a new file, app.pupnet.conf, which will be a "light weight" configuration file lacking the documentation comments.

To generate a "verbose" file with documentation under a custom name:

pupnet ProjectName --new conf --verbose

In fact, we can generate a complete set of files, as follows:

pupnet ProjectName --new all --verbose

This creates not only the pupnet.conf file, but the .desktop and a .metainfo.xml template as well.

BACKWARD COMPATIBILITY & UPGRADING YOUR CONFIGURATION

Where possible, new versions of PupNet will be backward compatible with existing pupnet.conf files. If ever this is not the case, it will be explicitly stated.

New configuration properties may be added and old ones removed or deprecated, however. Where a new PupNet version results in changes to configuration properties, you can upgrade an existing pupnet.conf file to the latest format using:

pupnet [file.pupnet.conf] --upgrade-conf

or

pupnet [file.pupnet.conf] --upgrade-conf --verbose

Your existing file will "backed-up" by appending an ".old" extension, and a new file written containing new properties with their default values.

Using the --verbose option (above), causes the new file to contain extensive document comments. Without it, the new file will be stripped of comments.

See also version specific changes below.

Version 1.4 Changes

PupNet version 1.4.0 introduced new AppDescription and AppChangeFile configuration properties. If you wish to make use of them, populate AppDescription with a longer application description (example below), and point AppChangeFile to a changelog or README file containing formatted version information.

AppDescription = """
    Hello World demonstrates all the major features of building distributable packages with PupNet.
    It can be built for all package kinds, including AppImage, Flatpak, DEB and RPM formats on Linux,
    and as a Setup file on Windows. It provides an example of using desktop and AppStream metadata files,
    as well as icons and post-publish scripts.

    On execution, the Hello World program displays command arguments and assembly information. The assembly
    version confirms that version information, provided in the deployment configuration, was successfully passed
    through the build system, to the application.
"""

AppChangeFile = CHANGES.txt

See above for the required format of AppChangeFile content.

Additionally, you will need to add a couple of macros to your AppStream metadata file, as follows, in order to fully make use of these new features:

<description>
    ${APPSTREAM_DESCRIPTION_XML}
</description>

Here, you may replace your default description text, but keep any other language text. And:

<releases>
    ${APPSTREAM_CHANGELOG_XML}
</releases>

With this one, you should remove existing version release information if ${APPSTREAM_CHANGELOG_XML} is going to be populated from AppChangeFile.

In addition to AppStream metadata, the AppDescription content is now also used in the construction of RPM and DEB packages.

HELP SYSTEM REFERENCE

Command Arguments

Type pupnet --help to display command arguments as expected.

PupNet Deploy 1.8.0
See also: https://github.com/kuiperzone/PupNet-Deploy

USAGE:
    pupnet [<file.pupnet.conf>] [--option-n value-n]

Example:
    pupnet app.pupnet.conf -y -r linux-arm64

Always give .pupnet.conf file first. If .pupnet.conf file is omitted, the default is the one in the
working directory.

Build Options:
   -k, --kind <zip|appimage|deb|rpm|flatpak|setup>
   Package output kind. If omitted, one is chosen according to the runtime (AppImage on linux).
   Example: pupnet HelloWorld -k Flatpak

   -r, --runtime <linux-x64|linux-arm64|win-x64...>
   Dotnet publish runtime identifier. Default: linux-x64.
   Valid examples include: 'linux-x64', 'linux-arm64' and 'win-x64' etc.
   See: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog

   -c, --build <Release|Debug>
   Optional build target (or 'Configuration' in dotnet terminology).
   Value should be 'Release' or 'Debug' only. Default: Release.

   -j, --project <csproj path>
   Optional path to the .csproj file or directory containing it. Overrides DotnetProjectPath
   in the conf file.

   -e, --clean
   Call 'dotnet clean' prior to 'dotnet publish'. Default: false.

   -v, --app-version <version[release]>
   Specifies application version-release in form 'version[release]', where value in square
   brackets is package release. Overrides AppVersionRelease in conf file.
   Example: 1.2.3[1].

   -p, --property <name=value>
   Specifies a property to be supplied to dotnet publish command. Do not use for app versioning.
   Separate multiple values with comma. Example: -p DefineConstants=TRACE,DEBUG

   --arch <value>
   Force target architecture, i.e. as 'x86_64', 'amd64' or 'aarch64' etc. Note that this is
   not normally necessary as, in most cases, the architecture is defined by the dotnet runtime-id
   and will be successfully detected automatically. However, in the event of a problem, the value
   explicitly supplied here will be used to override. It should be provided in the form
   expected by the underlying package builder (i.e. rpmbuild, appimagetool or InnoSetup etc.).

   -o, --output <filename>
   Force package output filename. Normally this is derived from parameters in the configuration.
   This value will be used to override. Example: -o AppName.AppImage

   --verbose
   Indicates verbose output when building. It is used also with --new option.

   -u, --run
   Performs a test run of the application after successful build (where supported).

   -y, --skip-yes
   Skips confirmation prompts (assumes yes).

Other Options:

   -n, --new <conf|desktop|meta|all> [--verbose] [--skip-yes]
   Creates a new empty conf file or associated file (i.e. desktop of metadata) for a new project.
   A base file name may optionally be given. If --verbose is used, a configuration file with
   documentation comments is generated. Use 'all' to generate a full set of configuration assets.
   Example: pupnet HelloWorld -n all --verbose

   --upgrade-conf [--verbose] [--skip-yes]
   Upgrades supplied .pupnet.conf file to latest version parameters. For example, if the
   conf file was created with program version 1.1 and new parameters where added in version
   1.2, this command will upgrade the file by adding new parameters with default values.
   If --verbose is used, a configuration file with documentation comments is generated.
   Example: pupnet file.pupnet.conf --upgrade-conf --verbose

   -h, --help <args|macro|conf>
   Show help information. Optional value specifies what kind of information to display.
   Default is 'args'. Example: pupnet -h macro

   --version
   Show version and associated information.

Macro Reference

Type pupnet --help macro to see supported macro reference information:

Macro variables may be used with the following configuration items:
DesktopFile, MetaFile, DotnetPublishArgs, DotnetPostPublish and DotnetPostPublishOnWindows.

IMPORTANT: Always use the ${MACRO_NAME} form, and not $MACRO_NAME.

** ${APP_BASE_NAME} **
Gives the AppBaseName value from the pupnet.conf file
Example: ${APP_BASE_NAME} = HelloWorld

** ${APP_FRIENDLY_NAME} **
Gives the AppFriendlyName value from the pupnet.conf file
Example: ${APP_FRIENDLY_NAME} = Hello World

** ${APP_ID} **
Gives the AppId value from the pupnet.conf file
Example: ${APP_ID} = net.example.helloworld

** ${APP_LICENSE_ID} **
Gives the AppLicenseId value from the pupnet.conf file
Example: ${APP_LICENSE_ID} = LicenseRef-Proprietary

** ${APP_SHORT_SUMMARY} **
Gives the AppShortSummary value from the pupnet.conf file
Example: ${APP_SHORT_SUMMARY} = A HelloWorld application

** ${APP_VERSION} **
Application version, excluding package-release extension
Example: ${APP_VERSION} = 1.0.0

** ${APPSTREAM_CHANGELOG_XML} **
AppStream changelog XML content (use within the <releases> element only)

** ${APPSTREAM_DESCRIPTION_XML} **
AppStream application description XML (use within the <description> element only)

** ${BUILD_APP_BIN} **
Application build directory (i.e. the output of dotnet publish or C++ make)
Example: ${BUILD_APP_BIN} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir/usr/bin

** ${BUILD_ARCH} **
Build architecture: x64, arm64, arm or x86 (may differ from package output notation)
Example: ${BUILD_ARCH} = x64

** ${BUILD_DATE} **
Build date in 'yyyy-MM-dd' format
Example: ${BUILD_DATE} = 2023-05-05

** ${BUILD_ROOT} **
Root of the temporary application build directory
Example: ${BUILD_ROOT} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir

** ${BUILD_SHARE} **
Linux 'usr/share' build directory under BuildRoot (empty for some deployments)
Example: ${BUILD_SHARE} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir/usr/share

** ${BUILD_TARGET} **
Release or Debug (Release unless explicitly specified)
Example: ${BUILD_TARGET} = Release

** ${BUILD_YEAR} **
Build year as 'yyyy'
Example: ${BUILD_YEAR} = 2023

** ${DEPLOY_KIND} **
Deployment output kind: appimage, flatpak, rpm, deb, setup, zip
Example: ${DEPLOY_KIND} = appimage

** ${DESKTOP_INTEGRATE} **
Gives the logical not of ${DESKTOP_NODISPLAY}
Example: ${DESKTOP_INTEGRATE} = true

** ${DESKTOP_NODISPLAY} **
Gives the DesktopNoDisplay value from the pupnet.conf file
Example: ${DESKTOP_NODISPLAY} = false

** ${DESKTOP_TERMINAL} **
Gives the DesktopTerminal value from the pupnet.conf file
Example: ${DESKTOP_TERMINAL} = true

** ${DOTNET_RUNTIME} **
Dotnet publish runtime identifier used (RID)
Example: ${DOTNET_RUNTIME} = linux-x64

** ${INSTALL_BIN} **
Path to application directory on target system (not the build system)
Example: ${INSTALL_BIN} = usr/bin

** ${INSTALL_EXEC} **
Path to application executable on target system (not the build system)
Example: ${INSTALL_EXEC} = usr/bin/HelloWorld

** ${LOCAL_DIRECTORY} **
The pupnet.conf file directory

** ${PACKAGE_RELEASE} **
Package release version
Example: ${PACKAGE_RELEASE} = 1

** ${PRIME_CATEGORY} **
Gives the PrimeCategory value from the pupnet.conf file
Example: ${PRIME_CATEGORY} = Utility

** ${PUBLISHER_COPYRIGHT} **
Gives the PublisherCopyright value from the pupnet.conf file
Example: ${PUBLISHER_COPYRIGHT} = Copyright (C) Acme Ltd 2023

** ${PUBLISHER_EMAIL} **
Gives the PublisherEmail value from the pupnet.conf file
Example: ${PUBLISHER_EMAIL} = contact@example.net

** ${PUBLISHER_LINK_NAME} **
Gives the PublisherLinkName value from the pupnet.conf file
Example: ${PUBLISHER_LINK_NAME} = Project Page

** ${PUBLISHER_LINK_URL} **
Gives the PublisherLinkUrl value from the pupnet.conf file
Example: ${PUBLISHER_LINK_URL} = https://example.net

** ${PUBLISHER_NAME} **
Gives the PublisherName value from the pupnet.conf file
Example: ${PUBLISHER_NAME} = The Hello World Team

Configuration Reference

Type pupnet --help conf to see supported configuration reference information:

########################################
# APP PREAMBLE
########################################

** AppBaseName **
Mandatory application base name. This MUST BE the base name of the main executable file. It should NOT
include any directory part or extension, i.e. do not append '.exe' or '.dll'. It should not contain
spaces or invalid filename characters.
Example: AppBaseName = HelloWorld

** AppFriendlyName **
Mandatory application friendly name.
Example: AppFriendlyName = Hello World

** AppId **
Mandatory application ID in reverse DNS form. This should stay constant for lifetime of the software.
Example: AppId = net.example.helloworld

** AppVersionRelease **
Mandatory application version and package release of form: 'VERSION[RELEASE]'. Use optional square
brackets to denote package release, i.e. '1.2.3[1]'. Release refers to a change to the deployment
package, rather the application. If release part is absent (i.e. '1.2.3'), the release value defaults
to '1'. Note that the version-release value given here may be overridden from the command line.
Example: AppVersionRelease = 1.0.0[1]

** AppShortSummary **
Mandatory single line application summary text in default (English) language.
Example: AppShortSummary = A HelloWorld application

** AppDescription **
Multi-line (surround with triple """ quotes) application description which provides longer explanation
than AppShortSummary in default language. Optional but it is recommended to specify this. Text
separated by an empty line will be treated as separate paragraphs. Avoid complex formatting, and do not
use HTML or markdown, other than list items begining with "* ", "+ " or "- ". This content is
used by package builders where supported, including RPM and DEB, and is used to populate the
${APPSTREAM_DESCRIPTION_XML} element used within AppStream metadata.

** AppLicenseId **
Mandatory application license ID. This should be one of the recognized SPDX license
identifiers, such as: 'MIT', 'GPL-3.0-or-later' or 'Apache-2.0'. For a proprietary or
custom license, use 'LicenseRef-Proprietary' or 'LicenseRef-LICENSE'.
Example: AppLicenseId = LicenseRef-Proprietary

** AppLicenseFile **
Optional path to application copyright/license text file. If provided, it will be packaged with the
application and used with package builders where supported.
Example: AppLicenseFile = LICENSE.txt

** AppChangeFile **
Optional path to application changelog file. IMPORTANT. If given, this file should contain version
information in a predefined format. Namely, it should contain one or more version headings of form:
'+ VERSION;DATE', under which are to be listed change items of form: '- Change description'. Formatted
information will be parsed and used to expand the ${APPSTREAM_CHANGELOG_XML} macro used
for AppStream metadata (superfluous text is ignored, so the file may also contain README information).
The given file will also be packaged with the application verbatim. See: https://github.com/kuiperzone/PupNet-Deploy.
Example: AppChangeFile = CHANGELOG.txt

########################################
# PUBLISHER
########################################

** PublisherName **
Mandatory publisher, group or creator.
Example: PublisherName = The Hello World Team

** PublisherCopyright **
Optional copyright statement.
Example: PublisherCopyright = Copyright (C) Acme Ltd 2024

** PublisherLinkName **
Optional publisher or application web-link name. Note that Windows Setup packages
require both PublisherLinkName and PublisherLinkUrl in order to include the link as
an item in program menu entries. Do not modify name, as may leave old entries in updated installations.
Example: PublisherLinkName = Project Page

** PublisherLinkUrl **
Publisher or application web-link URL. Although optional, it should be considered mandatory if using
MetaFile
Example: PublisherLinkUrl = https://example.net

** PublisherEmail **
Publisher or maintainer email contact. Although optional, some package builders (i.e. DEB) require it
and may warn or fail unless provided.
Example: PublisherEmail = contact@example.net

########################################
# DESKTOP INTEGRATION
########################################

** DesktopNoDisplay **
Boolean (true or false) which indicates whether the application is hidden on the desktop. It is used to
populate the 'NoDisplay' field of the .desktop file. The default is false. Setting to true will also
cause the main application start menu entry to be omitted for Windows Setup.
Example: DesktopNoDisplay = false

** DesktopTerminal **
Boolean (true or false) which indicates whether the application runs in the terminal, rather than
providing a GUI. It is used to populate the 'Terminal' field of the .desktop file.
Example: DesktopTerminal = true

** DesktopFile **
Optional path to a Linux desktop file. If empty (default), one will be generated automatically from
the information in this file. Supplying a custom file, however, allows for mime-types and
internationalisation. If supplied, the file MUST contain the line: 'Exec=${INSTALL_EXEC}'
in order to use the correct install location. Other macros may be used to help automate the content.
Note. PupNet Deploy can generate you a desktop file. Use --help and 'pupnet --help macro' for reference.
See: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
Example: DesktopFile = Deploy/app.desktop

** StartCommand **
Optional command name to start the application from the terminal. If, for example, AppBaseName is
'Zone.Kuiper.HelloWorld', the value here may be set to a simpler and/or lower-case variant such as
'helloworld'. It must not contain spaces or invalid filename characters. Do not add any extension such
as '.exe'. If empty, the application will not be in the path and cannot be started from the command line.
For Windows Setup packages, see also SetupCommandPrompt. StartCommand is not
supported for all packages kinds (i.e. Flatpak). Default is empty (none).
Example: StartCommand = helloworld

** PrimeCategory **
Optional category for the application. The value should be one of the recognized Freedesktop top-level
categories, such as: Audio, Development, Game, Office, Utility etc. Only a single value should be
provided here which will be used, where supported, to populate metadata. The default is empty.
See: https://specifications.freedesktop.org/menu-spec/latest/apa.html
Example: PrimeCategory = Utility

** MetaFile **
Path to AppStream metadata file. It is optional, but recommended as it is used by software centers.
Note. The contents of the files may use macro variables. Use 'pupnet --help macro' for reference.
See: https://docs.appimage.org/packaging-guide/optional/appstream.html
Example: MetaFile = Deploy/app.metainfo.xml

** IconFiles **
Optional icon file paths. The value may include multiple filenames separated with semicolon or given
in multi-line form. Valid types are SVG, PNG and ICO (ICO ignored on Linux). Note that the inclusion
of a scalable SVG is preferable on Linux, whereas PNGs must be one of the standard sizes and MUST
include the size in the filename in the form: name.32x32.png' or 'name.32.png'.
Example: IconFiles = """
    app.ico
    app.svg
    app.16x16.png
    app.32x32.png
    app.64x64.png
"""

########################################
# DOTNET PUBLISH
########################################

** DotnetProjectPath **
Optional path relative to this file in which to find the dotnet project (.csproj) file, or the
directory containing it. If empty (default), a single project file is expected under the same
directory as this file. IMPORTANT. If set to 'NONE', dotnet publish is disabled
(i.e. not called). Instead, only DotnetPostPublish is called.
Example: DotnetProjectPath = Source

** DotnetPublishArgs **
Optional arguments supplied to 'dotnet publish'. Do NOT include '-r' (runtime), or '-c' (configuration)
here as they will be added according to command line arguments. Typically you want as a minimum:
'-p:Version=${APP_VERSION} --self-contained true'. Additional useful arguments include:
'-p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishReadyToRun=true
-p:PublishTrimmed=true -p:TrimMode=link'. Note. This value may use macro variables. Use 'pupnet --help macro'
for reference. See: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish
Example: DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false

** DotnetPostPublish **
Post-publish (or standalone build) command on Linux (ignored on Windows). It is called after dotnet
publish, but before the final output is built. This could, for example, be a script which copies
additional files into the build directory given by ${BUILD_APP_BIN}. The working directory will be
the location of this file. This value is optional, but becomes mandatory if DotnetProjectPath equals
'NONE'. Note. This value may use macro variables. Additionally, scripts may use these as environment
variables. Use 'pupnet --help macro' for reference.
Example: DotnetPostPublish = post-publish.sh

** DotnetPostPublishOnWindows **
Post-publish (or standalone build) command on Windows (ignored on Linux). This should perform
the equivalent operation, as required, as DotnetPostPublish, but using DOS commands and batch
scripts. Multiple commands may be specified, separated by semicolon or given in multi-line form.
Note. This value may use macro variables. Additionally, scripts may use these as environment
variables. Use 'pupnet --help macro' for reference.
Example: DotnetPostPublishOnWindows = post-publish.bat

########################################
# PACKAGE OUTPUT
########################################

** PackageName **
Optional package name (excludes version etc.). If empty, defaults to AppBaseName. However, it is
used not only to specify the base output filename, but to identify the application in DEB and RPM
packages. You may wish, therefore, to ensure that the value represents a unique name. Naming
requirements are strict and must contain only alpha-numeric and '-', '+' and '.' characters.
Example: PackageName = HelloWorld

** OutputDirectory **
Output directory, or subdirectory relative to this file. It will be created if it does not exist and
will contain the final deploy output files. If empty, it defaults to the location of this file.
Example: OutputDirectory = Deploy/OUT

########################################
# APPIMAGE OPTIONS
########################################

** AppImageArgs **
Additional arguments for use with appimagetool. Useful for signing. Default is empty.
Example: AppImageArgs = --sign

** AppImageVersionOutput **
Boolean (true or false) which sets whether to include the application version in the AppImage filename,
i.e. 'HelloWorld-1.2.3-x86_64.AppImage'. Default is false. It is ignored if the output filename is
specified at command line.
Example: AppImageVersionOutput = false

########################################
# FLATPAK OPTIONS
########################################

** FlatpakPlatformRuntime **
The runtime platform. Invariably for .NET (inc. Avalonia), this should be 'org.freedesktop.Platform'.
Refer: https://docs.flatpak.org/en/latest/available-runtimes.html
Example: FlatpakPlatformRuntime = org.freedesktop.Platform

** FlatpakPlatformSdk **
The platform SDK. Invariably for .NET (inc. Avalonia applications) this should be 'org.freedesktop.Sdk'.
The SDK must be installed on the build system.
Example: FlatpakPlatformSdk = org.freedesktop.Sdk

** FlatpakPlatformVersion **
The platform runtime version. The latest available version may change periodically.
Refer to Flatpak documentation.
Example: FlatpakPlatformVersion = 23.08

** FlatpakFinishArgs **
Flatpak manifest 'finish-args' sandbox permissions. Optional, but if empty, the application will have
extremely limited access to the host environment. This option may be used to grant required
application permissions. Values here should be prefixed with '--' and separated by semicolon or given
in multi-line form. Refer: https://docs.flatpak.org/en/latest/sandbox-permissions.html
Example: FlatpakFinishArgs = """
    --socket=wayland
    --socket=x11
    --filesystem=host
    --share=network
"""

** FlatpakBuilderArgs **
Additional arguments for use with flatpak-builder. Useful for signing. Default is empty.
See flatpak-builder --help.
Example: FlatpakBuilderArgs = --gpg-keys=FILE

########################################
# RPM OPTIONS
########################################

** RpmAutoReq **
Boolean (true or false) which specifies whether to build the RPM package with 'AutoReq' equal to yes or no.
For dotnet application, the value should typically be false, but see RpmRequires below.
Refer: https://rpm-software-management.github.io/rpm/manual/spec.html
Example: RpmAutoReq = false

** RpmAutoProv **
Boolean (true or false) which specifies whether to build the RPM package with 'AutoProv' equal to yes or no.
Refer: https://rpm-software-management.github.io/rpm/manual/spec.html
Example: RpmAutoProv = true

** RpmRequires **
Optional list of RPM dependencies. The list may include multiple values separated with semicolon or given
in multi-line form. If empty, a self-contained dotnet package will successfully run on many (but not all)
Linux distros. In some cases, it will be necessary to explicitly specify additional dependencies.
Default values are recommended for use with dotnet and RPM packages at the time of writing.
For updated information, see: https://learn.microsoft.com/en-us/dotnet/core/install/linux-rhel#dependencies
Example: RpmRequires = """
    krb5-libs
    libicu
    openssl-libs
    zlib
"""

########################################
# DEBIAN OPTIONS
########################################

** DebianRecommends **
Optional list of Debian dependencies. The list may include multiple values separated with semicolon or given
in multi-line form. If empty, a self-contained dotnet package will successfully run on many (but not all)
Linux distros. In some cases, it will be necessary to explicitly specify additional dependencies.
Default values are recommended for use with dotnet and Debian packages at the time of writing.
For updated information, see: https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#dependencies
Example: DebianRecommends = """
    libc6
    libgcc1
    libgcc-s1
    libgssapi-krb5-2
    libicu
    libssl
    libstdc++6
    libunwind
    zlib1g
"""

########################################
# WINDOWS SETUP OPTIONS
########################################

** SetupGroupName **
Optional application group name used as the Start Menu folder and install directory under Program Files.
Specifically, it is used to define the InnoSetup DefaultGroupName and DefaultDirName parameters.
If empty (default), suitable values are used based on your application.
See: https://jrsoftware.org/ishelp/index.php?topic=setup_defaultgroupname
Example: SetupGroupName = HelloWorld Demo

** SetupAdminInstall **
Boolean (true or false) which specifies whether the application is to be installed in administrative
mode, or per-user. Default is false. See: https://jrsoftware.org/ishelp/topic_admininstallmode.htm
Example: SetupAdminInstall = false

** SetupCommandPrompt **
Optional command prompt title. The Windows installer will NOT add your application to the path. However,
if your package contains a command-line utility, setting this value will ensure that a 'Command Prompt'
program menu entry is added (with this title) which, when launched, will open a dedicated command
window with your application directory in its path. Default is empty. See also StartCommand.
Example: SetupCommandPrompt = Command Prompt

** SetupMinWindowsVersion **
Mandatory value which specifies minimum version of Windows that your software runs on. Windows 8 = 6.2,
Windows 10/11 = 10. Default: 10. See: https://jrsoftware.org/ishelp/topic_setup_minversion.htm
Example: SetupMinWindowsVersion = 10

** SetupSignTool **
Optional name and parameters of the Sign Tool to be used to digitally sign: the installer,
uninstaller, and contained exe and dll files. If empty, files will not be signed.
See: https://jrsoftware.org/ishelp/topic_setup_signtool.htm

** SetupSuffixOutput **
Optional suffix for the installer output filename. The default is empty, but you may wish set it to:
'Setup' or similar. This, for example, will output a file of name: HelloWorldSetup-x86_64.exe
Ignored if the output filename is specified at command line.
Example: SetupSuffixOutput = Setup

** SetupVersionOutput **
Boolean (true or false) which sets whether to include the application version in the setup filename,
i.e. 'HelloWorld-1.2.3-x86_64.exe'. Default is false. Ignored if the output filename is specified
at command line.
Example: SetupVersionOutput = true

FAQs & GOTCHAS

NETSDK1194: The "--output" option isn't supported

From .NET7 ownward, the dotnet publish no longer accepts a .sln file or directory containing one as input. It's current behaviour for .NET8.0 is to warn rather than fail but this may change in a future .NET release.

For your pupnet.conf files, the solution is to either place the conf file in the same directory as your .csproj file, or specify the .csproj file location using the DotnetProjectPath parameter.

See also: Solution-level --output option no longer valid for build-related commands.

Virtual Box & Symlinks

If you are using VirtualBox with your project, note that symbolic links are disabled within shared folders by VirtualBox itself, and this may cause problems with generating AppImages. To overcome this, copy your entire project to your home directory in the virtual machine. Alternatively, it is possible to enable shared-folder symlinks in VirtualBox.

Package Naming is not Consistent

You may notice that PupNet outputs differences in package naming styles. For example:

PupNet-Deploy.x86_64.AppImage
pupnet-deploy_0.0.1-1_amd64.deb

PupNet follows the naming conventions used with the respective packages. This includes, for example, different CPU architecture naming conventions. With some package naming styles, it is normal to include the version in the filename, but not in others.

Package Cannot be Removed using Gnome Software Center

If you install your Flatpak, RPM or DEB package directly from a local file (rather than a repository) they will, courtesy of your AppStream metadata, show up in the Gnome Software Center, as expected. However, you may find that they cannot be launched or removed using the GUI.

Instead, they must be removed from the command line, like so:

sudo flatpak uninstall zone.kuiper.helloworld

or:

sudo dnf remove helloworld

or:

sudo apt remove helloworld

This is not an issue with PupNet or AppStream metadata. Rather, having been installed from file, the Gnome Software Center lacks certain other metadata it expects had the package originated from a repository. See here for information.

ADDITIONAL INFORMATION

Brief Discussion on Past & Future

PupNet Deploy began life as a bash script called "Publish-AppImage for .NET":

Publish-AppImage

At the time, I was excited by Flatpak and it was my original intention to add Flatpak support to Publish-AppImage. However, it was difficult to handle the increased complexity in a bash script, so I re-wrote everything as a C# application and PupNet Deploy is the result.

In the process, however, I had cause to reflect on certain things, including the fact that the security model of Flatpak is broken IMHO. This came about because I intended to use Flatpak to deploy my other application project, but found that there are several important scenarios which Flatpak cannot support, including the deployment of development tools. Regardless, I thought it useful for developers to be able ship software in formats convenient for users, and recognise that Flatpak is a popular packaging technology. However, I felt that RPM and Debian formats should be added in order to provide alternatives where Flatpak is unsuitable.

Notes on Extending PupNet

Anyone wishing to extend PupNet, should study how the existing RpmBuilder, FlatpakBuilder and Windows SetupBuilder classes override and extend the behaviour of the PackageBuilder base class. The PackageBuilder base class is Linux centric, with unused directories and properties being set to null and ignored for the Windows Setup and Zip builders.

Moreover, a new enum value would need to be added to the PackageKind type. It would help to do a search on existing PackageKind values, and add the new type behaviour to switch statements wherever encountered, including the BuilderFactory class.

Please do feel free to post questions to the Github Discussion area. Where possible, I will be happy to respond.

An Application which uses PupNet Deploy

AvantGarde is a cross-platform XAML previewer for the C# Avalonia Framework, and the primary previewer solution when developing on Linux.

AvantGarde Screenshot

Copyright & License

Copyright (C) Andy Thomas, 2023. Website: https://kuiper.zone

PupNet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

PupNet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with PupNet. If not, see https://www.gnu.org/licenses/.

Embedded Assets

PupNet embeds "appimagetool", from the "AppImageKit". AppImageKit is Copyright (C) 2004-20 Simon Peter: https://github.com/AppImage/AppImageKit

Non-code Assets

Images and non-code assets are not subject to AGPL.

Project Logo: Copyright (C) Andy Thomas, 2023.

All other copyright and trademarks are property of respective owners.

If you like this project, don't forget to like and share.

About

PupNet Deploy is a cross-platform deployment utility which packages your .NET project as a ready-to-ship installation file in a single step.

License:GNU Affero General Public License v3.0


Languages

Language:C# 99.9%Language:Shell 0.1%