Skip to content

Commit

Permalink
.msi + winget package initial support
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyberboss committed Jun 24, 2023
1 parent e147256 commit 5f353b4
Show file tree
Hide file tree
Showing 20 changed files with 1,410 additions and 48 deletions.
1 change: 1 addition & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ coverage:
comment:
layout: "header, diff, changes"
ignore:
- "build"
- "src/Tgstation.Server.Host/Database/Design"
- "src/Tgstation.Server.Host/Database/Migrations/MySqlDatabaseContextModelSnapshot.cs"
- "src/Tgstation.Server.Host/Database/Migrations/PostgresSqlDatabaseContextModelSnapshot.cs"
Expand Down
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ You can of course, as always, ask for help at [#coderbus](irc://irc.rizon.net/co

### Development Environment

You need the Dotnet 6.0 SDK and npm>=v5.7 (in your PATH) to compile the server. In order to build the service version you also need a .NET 4.7.1 build chain
You need the Dotnet 6.0 SDK and npm>=v5.7 (in your PATH) to compile the server. In order to build the service version you also need a .NET 4.7.2 build chain. In order to build the .msi installer, you'll need [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) or greater and the [Visual Studio Installer Projects Extension](https://marketplace.visualstudio.com/items?itemName=VisualStudioClient.MicrosoftVisualStudio2022InstallerProjects).

The recommended IDE is Visual Studio 2019 which has installation options for both of these.

Expand Down
48 changes: 46 additions & 2 deletions .github/workflows/ci-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -920,11 +920,39 @@ jobs:
name: packaging-debian
path: tgstation-server-v${{ env.TGS_VERSION }}.debian.packaging.tar.xz

build-msi:
name: Build .msi Package
needs: start-ci-run-gate
runs-on: windows-latest
if: "!(cancelled() || failure()) && needs.start-ci-run-gate.result == 'success'"
steps:
- name: Setup dotnet
uses: actions/setup-dotnet@v2
with:
dotnet-version: ${{ env.TGS_DOTNET_VERSION }}

- name: Setup VS Dev Environment
uses: seanmiddleditch/gha-setup-vsdevenv@v4

- name: Disable Out of Process Building
working-directory: C:/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/CommonExtensions/Microsoft/VSI/DisableOutOfProcBuild
run: ./DisableOutOfProcBuild.exe

- name: Build .vdproj
shell: powershell
run: build/package/winget/build_package.ps1

- name: Upload .msi
uses: actions/upload-artifact@v3
with:
name: packaging-windows
path: packaging/build/package/winget/Tgstation.Server.Host.Service.Msi/Release/tgstation-server.msi

deployment-gate:
name: Deployment Gate
needs: [ dox-build, docker-build, build-deb, validate-openapi-spec, upload-code-coverage ]
needs: [ dox-build, docker-build, build-deb, validate-openapi-spec, upload-code-coverage, build-msi ]
runs-on: ubuntu-latest
if: "!(cancelled() || failure()) && needs.dox-build.result == 'success' && needs.docker-build.result == 'success' && needs.build-deb.result == 'success' && needs.validate-openapi-spec.result == 'success' && needs.upload-code-coverage.result == 'success' && github.event_name == 'push'"
if: "!(cancelled() || failure()) && needs.dox-build.result == 'success' && needs.docker-build.result == 'success' && needs.build-deb.result == 'success' && needs.build-msi.result == 'success' && needs.validate-openapi-spec.result == 'success' && needs.upload-code-coverage.result == 'success' && github.event_name == 'push'"
steps:
- name: GitHub Requires at Least One Step for a Job
run: exit 0
Expand Down Expand Up @@ -1120,6 +1148,12 @@ jobs:
name: packaging-debian
path: packaging-debian

- name: Retrieve .msi
uses: actions/download-artifact@v3
with:
name: packaging-windows
path: packaging-windows

- name: Zip Artifacts
shell: powershell
run: |
Expand Down Expand Up @@ -1203,6 +1237,16 @@ jobs:
asset_name: tgstation-server-v${{ env.TGS_VERSION }}.debian.packaging.tar.xz
asset_content_type: application/x-tar

- name: Upload .msi
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.DEV_PUSH_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./packaging-windows/tgstation-server.msi
asset_name: tgstation-server.msi
asset_content_type: application/octet-stream

deploy-docker:
name: Deploy TGS (Docker)
needs: deploy-tgs
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ release_notes.md
*nupkg
*.sqlite3
packaging/
build/package/winget/Tgstation.Server.Host.Service.Msi/Release/
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,39 @@ Follow the instructions for your OS below.

#### Windows

Download and install the [ASP .NET Core Runtime (>= v6.0)](https://dotnet.microsoft.com/download/dotnet/6.0) (Choose the option to `Run Server Apps` for your system). If you plan to install tgstation-server as a Windows service, you should also ensure that your .NET Framework runtime version is >= v4.7.2 (Most modern systems have it by default. Download can be found on same page). Ensure that the `dotnet` executable file is in your system's `PATH` variable (or that of the user's that will be running the server), you can test this by opening a command prompt and running `dotnet --list-runtimes`.
##### Installer

If you don't have it installed already, download and install the [ASP .NET Core Runtime (>= v6.0)](https://dotnet.microsoft.com/download/dotnet/6.0). Ensure that the `dotnet` executable file is in your system's `PATH` variable (or that of the user's that will be running the server). You can test this by opening a command prompt and running `dotnet --list-runtimes`.

You should also ensure that your .NET Framework runtime version is >= v4.7.2. Most modern systems have it by default so this isn't much of a concern. If, somehow, you don't have it installed, it can be downloaded [here](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472).

[Download the latest release .msi](https://github.com/tgstation/tgstation-server/releases/latest). Executing it will take you through the process of installing and configuring your server.

##### winget

If you have [winget]() installed. You can easily install the latest version of tgstation-server (provided Microsoft has approved the most recent package manifest).

Simply run the following command:
```sh
winget install tgstation-server
```

If you get an error like `This file does not have an app associated with it for performing this action.` run with the `--silent` flag:
```sh
winget install tgstation-server --silent
```

You won't be prompted to run the setup wizard. However, you can do so immediately after via the shortcut placed on your desktop.

NOTE:

`winget` should, theoretically, install the ASP .NET Core 6.0 Runtime as a pre-reqiusite. At the time of this writing, this functionality is untested (TODO). If the runtime isn't automatically installed for you, see above or below for steps on how to download and install it manually.

##### Manual

If you don't have it installed already, download and install the [ASP .NET Core Runtime (>= v6.0)](https://dotnet.microsoft.com/download/dotnet/6.0). Ensure that the `dotnet` executable file is in your system's `PATH` variable (or that of the user's that will be running the server). You can test this by opening a command prompt and running `dotnet --list-runtimes`.

You should also ensure that your .NET Framework runtime version is >= v4.7.2. Most modern systems have it by default so this isn't much of a concern. If, somehow, you don't have it installed, it can be downloaded [here](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472).

[Download the latest release .zip](https://github.com/tgstation/tgstation-server/releases/latest). You probably want the `ServerService` package. Choose `ServerConsole` if you prefer not to use the Windows service.

Expand All @@ -36,7 +68,7 @@ If you wish to install the TGS as a service, run `Tgstation.Server.Host.Service.

Should you want a clean start, be sure to first uninstall the service by running `Tgstation.Server.Host.Service.exe -u` from the command line.

If using the console version, run ./tgs.bat in the root of the installation directory. Ctrl+C will close the server, terminating all live game instances.
If using the console version, run `./tgs.bat` in the root of the installation directory. Ctrl+C will close the server, terminating all live game instances.

#### Linux

Expand Down
22 changes: 11 additions & 11 deletions src/Tgstation.Server.Host/manifest.xml → build/manifest.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="highestAvailable" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="highestAvailable" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using var process = new Process();

var installDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location)!;

process.StartInfo.WorkingDirectory = installDir;
process.StartInfo.FileName = Path.Combine(
process.StartInfo.WorkingDirectory,
"Tgstation.Server.Host.Service.exe");

/*
https://www.roelvanlisdonk.nl/2009/11/13/how-to-detect-unattended-installation-msiexec-quit-or-qn-in-youre-custom-action-with-c/
msiUILevelNoChange 0 Does not change UI level.
msiUILevelDefault 1 Uses default UI level.
msiUILevelNone 2 Silent installation.
msiUILevelBasic 3 Simple progress and error handling.
msiUILevelReduced 4 Authored UI and wizard dialog boxes suppressed.
msiUILevelFull 5 Authored UI with wizards, progress, and errors.
msiUILevelHideCancel 32 If combined with the msiUILevelBasic value, the installer shows progress dialog boxes but does not display a Cancel button on the dialog box to prevent users from canceling the installation.
msiUILevelProgressOnly 64 If combined with the msiUILevelBasic value, the installer displays progress dialog boxes but does not display any modal dialog boxes or error dialog boxes.
msiUILevelEndDialog 128 If combined with any above value, the installer displays a modal dialog box at the end of a successful installation or if there has been an error. No dialog box is displayed if the user cancels.
*/
var uiLevel = Int32.Parse(args[0]);

// leave it to MS to overcomplicate things
var interactive = uiLevel switch
{
0 or 1 or 4 or 5 => true,
_ => false,
};

var silent = uiLevel == 2;

var uninstall = args
.Any(arg => arg.Equals("--uninstall", StringComparison.OrdinalIgnoreCase));

var shortcut = uiLevel == 42069;

process.StartInfo.Arguments = uninstall
? "-u"
: shortcut
? "-c"
: $"-i -f {(interactive ? "-c" : String.Empty)} {(silent ? "-s" : String.Empty)}";

process.Start();

await process.WaitForExitAsync(CancellationToken.None); // DCT: None available

foreach (var installLogFile in Directory.EnumerateFiles(installDir, "*.log"))
File.Delete(installLogFile);

if (uninstall)
{
Directory.Delete(
Path.Combine(installDir, "lib"),
true);
}

if(shortcut && process.ExitCode == 0)
{
Console.WriteLine();
Console.Write("tgstation-server is now configured. Would you like to (re)start the service? (Y/n): ");
var keyInfo = Console.ReadKey();
Console.WriteLine();
if (keyInfo.Key == ConsoleKey.Y || keyInfo.Key == ConsoleKey.Enter)
{
using (var stopService = new Process())
{
stopService.StartInfo.FileName = "sc";
stopService.StartInfo.Arguments = "stop tgstation-server";
stopService.Start();
await stopService.WaitForExitAsync(CancellationToken.None); // DCT: None available
}

using var startService = new Process();
startService.StartInfo.FileName = "sc";
startService.StartInfo.Arguments = "start tgstation-server";
startService.Start();
await startService.WaitForExitAsync(CancellationToken.None); // DCT: None available
}

Console.WriteLine("Press any key to exit this program...");
Console.ReadKey();
Console.WriteLine();
}

// returning non-zero can make the installation uninstallable, no thanks
return uninstall ? 0 : process.ExitCode;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ApplicationManifest>../../../manifest.xml</ApplicationManifest>
<ApplicationIcon>../../../tgs.ico</ApplicationIcon>
</PropertyGroup>

<ItemGroup>
<AdditionalFiles Include="../../../manifest.xml" />
</ItemGroup>
</Project>
Loading

0 comments on commit 5f353b4

Please sign in to comment.