Skip to content

Commit

Permalink
Self-contained instances (#3970)
Browse files Browse the repository at this point in the history
* Make instances self-contained

* Remove unneeded runsettings files

* Remove framework version check

* Make self-contained build only for release artifacts

* Remove workaround for fixed graph build bug

* Don't copy App.config to bin folder

* Update artifact exclusions

* Add DBPath to startup record

* Ensure that the correct config files are read

* Add more artifact exclusions

* Move duplicate instance files into separate zip file

* Update Installer for new zip layout

* Stop adding GC setting to app.config that isn't used

* Move transport artifacts back into instances

* Clean up unused list

* Remove unneeded zip filter support

* Update packaging tests to understand deploy changes

* Update InstallerEngine tests

* Build all projects with win-x64 RID when self-contained

* React to PR feedback

* Ensure RavenDB download script is used when WindowsSelfContained is true
  • Loading branch information
bording committed Mar 4, 2024
1 parent 824ebd9 commit b1b6eea
Show file tree
Hide file tree
Showing 66 changed files with 305 additions and 449 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/ci.yml
Expand Up @@ -44,10 +44,8 @@ jobs:
- name: Download RavenDB Server
shell: pwsh
run: ./tools/download-ravendb-server.ps1
- name: Restore
run: dotnet restore src
- name: Build
run: dotnet build src --configuration Release -graph --no-restore
run: dotnet build src --configuration Release -graph
- name: Zip PowerShell module
shell: pwsh
run: |
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/release.yml
Expand Up @@ -32,12 +32,10 @@ jobs:
- name: Download RavenDB Server
shell: pwsh
run: ./tools/download-ravendb-server.ps1
- name: Restore
run: dotnet restore src
- name: Build
run: dotnet build src --configuration Release -graph --no-restore
run: dotnet build src --configuration Release -graph --property:WindowsSelfContained=true
- name: Build ServiceControl Management
run: dotnet publish src\ServiceControl.Config\ServiceControl.Config.csproj --no-build --output assets
run: dotnet publish src\ServiceControl.Config\ServiceControl.Config.csproj --no-build --output assets --property:WindowsSelfContained=true
- name: Sign NuGet packages
uses: Particular/sign-nuget-packages-action@v1.0.0
with:
Expand Down
10 changes: 10 additions & 0 deletions src/Custom.Build.props
Expand Up @@ -22,6 +22,16 @@
<WriteMinVerProperties>false</WriteMinVerProperties>
</PropertyGroup>

<ItemGroup>
<InstanceName Include="Particular.ServiceControl" />
<InstanceName Include="Particular.ServiceControl.Audit" />
<InstanceName Include="Particular.ServiceControl.Monitoring" />
</ItemGroup>

<PropertyGroup Condition="'$(WindowsSelfContained)' == 'true'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>

<!-- workaround for https://github.com/microsoft/MSBuildSdks/issues/477 -->
<PropertyGroup>
<UseArtifactsOutput>false</UseArtifactsOutput>
Expand Down
7 changes: 5 additions & 2 deletions src/Directory.Packages.props
Expand Up @@ -69,13 +69,16 @@
</ItemGroup>

<ItemGroup Label="Versions to pin transitive references">
<PackageVersion Include="Microsoft.AspNetCore.JsonPatch " Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.JsonPatch" Version="8.0.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<GlobalPackageReference Include="Microsoft.Build.Artifacts" Version="6.1.10" />
<GlobalPackageReference Include="Microsoft.Build.CopyOnWrite" Version="1.0.302" />
<GlobalPackageReference Include="Particular.Packaging" Version="4.0.0" />
<GlobalPackageReference Include="Particular.Packaging" Version="4.1.0" />
</ItemGroup>

</Project>
@@ -0,0 +1,34 @@
{
"Version": "1.0.0",
"Definitions": [
{
"Name": "AzureServiceBus.EndpointOriented",
"DisplayName": "Azure Service Bus - Endpoint-oriented topology (Legacy)",
"TypeName": "ServiceControl.Transports.ASB.ASBEndpointTopologyTransportCustomization, ServiceControl.Transports.ASB",
"SampleConnectionString": "Endpoint=sb://[namespace].servicebus.windows.net; SharedSecretIssuer=<owner>;SharedSecretValue=<someSecret>;QueueLengthQueryDelayInterval=<IntervalInMilliseconds(Default=500ms)>",
"AvailableInSCMU": false,
"Removed": true,
"Aliases": [
"AzureServiceBus",
"Azure Service Bus - Endpoint-oriented topology (Old)",
"ServiceControl.Transports.LegacyAzureServiceBus.EndpointOrientedTopologyAzureServiceBusTransport, ServiceControl.Transports.LegacyAzureServiceBus",
"ServiceControl.Transports.ASB.ASBEndpointTopologyTransportCustomization, ServiceControl.Transports.ASB",
"NServiceBus.AzureServiceBusTransport, NServiceBus.Azure.Transports.WindowsAzureServiceBus"
]
},
{
"Name": "AzureServiceBus.Forwarding",
"DisplayName": "Azure Service Bus - Forwarding topology (Legacy)",
"TypeName": "ServiceControl.Transports.ASB.ASBForwardingTopologyTransportCustomization, ServiceControl.Transports.ASB",
"SampleConnectionString": "Endpoint=sb://[namespace].servicebus.windows.net; SharedSecretIssuer=<owner>;SharedSecretValue=<someSecret>;QueueLengthQueryDelayInterval=<IntervalInMilliseconds(Default=500ms)>",
"AvailableInSCMU": false,
"Removed": true,
"AutoMigrateTo": "NetStandardAzureServiceBus",
"Aliases": [
"Azure Service Bus - Forwarding topology (Legacy)",
"Azure Service Bus - Forwarding topology (Old)",
"ServiceControl.Transports.LegacyAzureServiceBus.ForwardingTopologyAzureServiceBusTransport, ServiceControl.Transports.LegacyAzureServiceBus"
]
}
]
}
@@ -0,0 +1,34 @@
{
"Version": "1.0.0",
"Definitions": [
{
"Name": "AzureServiceBus.EndpointOriented",
"DisplayName": "Azure Service Bus - Endpoint-oriented topology (Legacy)",
"TypeName": "ServiceControl.Transports.ASB.ASBEndpointTopologyTransportCustomization, ServiceControl.Transports.ASB",
"SampleConnectionString": "Endpoint=sb://[namespace].servicebus.windows.net; SharedSecretIssuer=<owner>;SharedSecretValue=<someSecret>;QueueLengthQueryDelayInterval=<IntervalInMilliseconds(Default=500ms)>",
"AvailableInSCMU": false,
"Removed": true,
"Aliases": [
"AzureServiceBus",
"Azure Service Bus - Endpoint-oriented topology (Old)",
"ServiceControl.Transports.LegacyAzureServiceBus.EndpointOrientedTopologyAzureServiceBusTransport, ServiceControl.Transports.LegacyAzureServiceBus",
"ServiceControl.Transports.ASB.ASBEndpointTopologyTransportCustomization, ServiceControl.Transports.ASB",
"NServiceBus.AzureServiceBusTransport, NServiceBus.Azure.Transports.WindowsAzureServiceBus"
]
},
{
"Name": "AzureServiceBus.Forwarding",
"DisplayName": "Azure Service Bus - Forwarding topology (Legacy)",
"TypeName": "ServiceControl.Transports.ASB.ASBForwardingTopologyTransportCustomization, ServiceControl.Transports.ASB",
"SampleConnectionString": "Endpoint=sb://[namespace].servicebus.windows.net; SharedSecretIssuer=<owner>;SharedSecretValue=<someSecret>;QueueLengthQueryDelayInterval=<IntervalInMilliseconds(Default=500ms)>",
"AvailableInSCMU": false,
"Removed": true,
"AutoMigrateTo": "NetStandardAzureServiceBus",
"Aliases": [
"Azure Service Bus - Forwarding topology (Legacy)",
"Azure Service Bus - Forwarding topology (Old)",
"ServiceControl.Transports.LegacyAzureServiceBus.ForwardingTopologyAzureServiceBusTransport, ServiceControl.Transports.LegacyAzureServiceBus"
]
}
]
}
Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RunSettingsFilePath>ServiceControl.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
Expand Down

This file was deleted.

Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RunSettingsFilePath>ServiceControl.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
Expand Down

This file was deleted.

Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RunSettingsFilePath>ServiceControl.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
Expand Down

This file was deleted.

Expand Up @@ -161,6 +161,7 @@ void RecordStartup()

var startupMessage = $@"
-------------------------------------------------------------
Database Path: {configuration.ServerConfiguration.DbPath}
Database Size: {ByteSize.FromBytes(dataSize).ToString("#.##", CultureInfo.InvariantCulture)}
Database Folder Size: {ByteSize.FromBytes(folderSize).ToString("#.##", CultureInfo.InvariantCulture)}
RavenDB Logging Level: {configuration.ServerConfiguration.LogsMode}
Expand Down
Expand Up @@ -23,7 +23,7 @@

<ItemGroup>
<!-- Artifact does not include RavenDBServer directory. Primary instance is responsible for copying that to deploy directory. -->
<Artifact Include="$(OutputPath)" DirExclude="RavenDBServer" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl.Audit\Persisters\RavenDB" />
<Artifact Include="$(OutputPath)" DirExclude=".db;.logs;RavenDBServer" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl.Audit\Persisters\RavenDB" />
</ItemGroup>

<ItemGroup>
Expand Down
Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RunSettingsFilePath>ServiceControl.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
Expand Down
7 changes: 0 additions & 7 deletions src/ServiceControl.Audit.UnitTests/ServiceControl.runsettings

This file was deleted.

3 changes: 3 additions & 0 deletions src/ServiceControl.Audit/Program.cs
Expand Up @@ -12,6 +12,7 @@
using Microsoft.Extensions.Hosting.WindowsServices;
using NServiceBus.Logging;
using ServiceControl.Audit.Persistence;
using ServiceControl.Configuration;
using ServiceControl.Transports;

class Program
Expand All @@ -23,6 +24,8 @@ static async Task Main(string[] args)
AssemblyLoadContext.Default.Resolving += ResolveAssembly;
AppDomain.CurrentDomain.UnhandledException += (s, e) => Logger.Error("Unhandled exception was caught.", e.ExceptionObject as Exception);

ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var arguments = new HostArguments(args);

if (arguments.Help)
Expand Down
11 changes: 10 additions & 1 deletion src/ServiceControl.Audit/ServiceControl.Audit.csproj
Expand Up @@ -6,6 +6,10 @@
<ApplicationIcon>Operations.ico</ApplicationIcon>
</PropertyGroup>

<PropertyGroup Condition="'$(WindowsSelfContained)' == 'true'">
<SelfContained>true</SelfContained>
</PropertyGroup>

<!-- Needed for build ordering -->
<Import Project="..\ProjectReferences.Persisters.Audit.props" />
<Import Project="..\ProjectReferences.Transports.props" />
Expand Down Expand Up @@ -36,7 +40,12 @@
</ItemGroup>

<ItemGroup>
<Artifact Include="$(OutputPath)" FileExclude="ServiceControl.Audit.exe.config;logfile.*.txt;nsb_log_*.txt;*-configuration.txt" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl.Audit\ServiceControl.Audit" />
<Content Remove="App.config" />
<None Include="App.config" />
</ItemGroup>

<ItemGroup>
<Artifact Include="$(OutputPath)" FileExclude="ServiceControl.Audit.dll.config" DirExclude=".logs" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl.Audit" />
</ItemGroup>

</Project>
8 changes: 1 addition & 7 deletions src/ServiceControl.Config/AppBootstrapper.cs
Expand Up @@ -92,15 +92,9 @@ protected override async void OnStartup(object sender, StartupEventArgs e)

var windowManager = GetInstance(typeof(IServiceControlWindowManager), null) as IServiceControlWindowManager;

if (DotnetVersionValidator.FrameworkRequirementsAreMissing(out var message))
{
message += $"{Environment.NewLine}{Environment.NewLine}Until the prerequisites are installed, no ServiceControl instances can be installed.";
await windowManager.ShowMessage("Missing prerequisites", message, acceptText: "I understand", hideCancel: true);
}

if (OldScmuCheck.OldVersionOfServiceControlInstalled(out var installedVersion))
{
message = $"An old version {installedVersion} of ServiceControl Management is installed, which will not work after installing new instances. Before installing ServiceControl 5 instances, you must either uninstall the {installedVersion} instance or update it to a 4.x version at least {OldScmuCheck.MinimumScmuVersion}.";
var message = $"An old version {installedVersion} of ServiceControl Management is installed, which will not work after installing new instances. Before installing ServiceControl 5 instances, you must either uninstall the {installedVersion} instance or update it to a 4.x version at least {OldScmuCheck.MinimumScmuVersion}.";
await windowManager.ShowMessage("Outdated Version Installed", message, acceptText: "I understand", hideCancel: true);
Application.Current.Shutdown(-1);
}
Expand Down
50 changes: 50 additions & 0 deletions src/ServiceControl.Configuration/ExeConfiguration.cs
@@ -0,0 +1,50 @@
namespace ServiceControl.Configuration
{
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

public static class ExeConfiguration
{
// ConfigurationManager on .NET is looking for {assembly}.dll.config files, but all previous versions of ServiceControl will have {assembly}.exe.config instead.
// This code reads in the exe.config files and adds all the values into the ConfigurationManager's collections.
public static void PopulateAppSettings(Assembly assembly)
{
var location = Path.GetDirectoryName(assembly.Location);
var assemblyName = Path.GetFileNameWithoutExtension(assembly.Location);
var exeConfigPath = Path.Combine(location, $"{assemblyName}.exe.config");
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = exeConfigPath };
var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

foreach (var key in configuration.AppSettings.Settings.AllKeys)
{
ConfigurationManager.AppSettings.Set(key, configuration.AppSettings.Settings[key].Value);
}

// The connection strings collection has had its read only flag set, so we need to clear it before we can add items to it
UnsetCollectionReadonly(ConfigurationManager.ConnectionStrings);

foreach (var connectionStringSetting in configuration.ConnectionStrings.ConnectionStrings.Cast<ConnectionStringSettings>())
{
ConfigurationManager.ConnectionStrings.Add(connectionStringSetting);
}

// Put the collection back into its previous state after we're done adding items to it
SetCollectionReadOnly(ConfigurationManager.ConnectionStrings);
}

static void UnsetCollectionReadonly(ConfigurationElementCollection collection)
{
ref bool field = ref GetReadOnlyFieldRef(collection);
field = false;

[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_readOnly")]
static extern ref bool GetReadOnlyFieldRef(ConfigurationElementCollection collection);
}

[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetReadOnly")]
static extern void SetCollectionReadOnly(ConfigurationElementCollection collection);
}
}
3 changes: 3 additions & 0 deletions src/ServiceControl.Monitoring/Program.cs
Expand Up @@ -7,6 +7,7 @@ namespace ServiceControl.Monitoring
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting.WindowsServices;
using NServiceBus.Logging;
using ServiceControl.Configuration;
using ServiceControl.Transports;

static class Program
Expand All @@ -18,6 +19,8 @@ static async Task Main(string[] args)
AssemblyLoadContext.Default.Resolving += ResolveAssembly;
AppDomain.CurrentDomain.UnhandledException += (s, e) => Logger.Error("Unhandled exception was caught.", e.ExceptionObject as Exception);

ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var arguments = new HostArguments(args);

LoadSettings(arguments);
Expand Down
11 changes: 10 additions & 1 deletion src/ServiceControl.Monitoring/ServiceControl.Monitoring.csproj
Expand Up @@ -6,6 +6,10 @@
<ApplicationIcon>Operations.ico</ApplicationIcon>
</PropertyGroup>

<PropertyGroup Condition="'$(WindowsSelfContained)' == 'true'">
<SelfContained>true</SelfContained>
</PropertyGroup>

<!-- Needed for build ordering -->
<Import Project="..\ProjectReferences.Transports.props" />

Expand All @@ -27,7 +31,12 @@
</ItemGroup>

<ItemGroup>
<Artifact Include="$(OutputPath)" FileExclude="ServiceControl.Monitoring.exe.config;logfile.*.txt;nsb_log_*.txt;*-configuration.txt" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl.Monitoring\ServiceControl.Monitoring" />
<Content Remove="App.config" />
<None Include="App.config" />
</ItemGroup>

<ItemGroup>
<Artifact Include="$(OutputPath)" FileExclude="ServiceControl.Monitoring.dll.config;nsb*.txt" DirExclude=".logs" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl.Monitoring" />
</ItemGroup>

</Project>
Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RunSettingsFilePath>ServiceControl.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions src/ServiceControl.Persistence.RavenDB/EmbeddedDatabase.cs
Expand Up @@ -162,6 +162,7 @@ static void RecordStartup(RavenPersisterSettings settings)

var startupMessage = $@"
-------------------------------------------------------------
Database Path: {settings.DatabasePath}
Database Size: {ByteSize.FromBytes(dataSize).ToString("#.##", CultureInfo.InvariantCulture)}
Database Folder Size: {ByteSize.FromBytes(folderSize).ToString("#.##", CultureInfo.InvariantCulture)}
RavenDB Logging Level: {settings.LogsMode}
Expand Down

0 comments on commit b1b6eea

Please sign in to comment.