From 84f5456148df0e8e9d58f67e0b4e69d3a3d4f125 Mon Sep 17 00:00:00 2001 From: Thomas Clark Date: Sat, 15 Jun 2024 21:32:51 +0100 Subject: [PATCH] build: distribute windows installer --- .github/workflows/release.yml | 26 ++++++ README.md | 6 ++ setup.iss | 89 +++++++++++++++++++ .../Common/HostingExtensions.cs | 37 -------- .../Data/SqliteDbConnectionFactory.cs | 12 +-- src/AzureAppConfigurationEmulator/Dockerfile | 1 + src/AzureAppConfigurationEmulator/Program.cs | 2 - 7 files changed, 128 insertions(+), 45 deletions(-) create mode 100644 setup.iss diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47ee490..2bcc2d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,8 @@ on: jobs: create_release: name: Create release + outputs: + upload_url: ${{ steps.create_release.outputs.upload_url }} runs-on: ubuntu-latest steps: - name: Create release @@ -16,6 +18,30 @@ jobs: with: release_name: ${{ github.ref }} tag_name: ${{ github.ref }} + publish_windows: + name: Publish Windows + needs: + - create_release + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Publish Windows + run: dotnet publish --configuration "Release" --runtime "win-${{ matrix.architecture }}" --self-contained "false" ".\src\AzureAppConfigurationEmulator\AzureAppConfigurationEmulator.csproj" + - name: Create installer + run: . "${env:ProgramFiles(x86)}\Inno Setup 6\iscc.exe" "/DArchitecture=${{ matrix.architecture }}" ".\setup.iss" + - name: Upload release asset + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: actions/upload-release-asset@v1 + with: + asset_content_type: application/vnd.microsoft.portable-executable + asset_name: azure-app-configuration-emulator-windows-${{ matrix.architecture }}.exe + asset_path: .\Output\mysetup.exe + upload_url: ${{ needs.create_release.outputs.upload_url }} + strategy: + matrix: + architecture: [arm64, x64] push_to_registry: name: Push to registry needs: diff --git a/README.md b/README.md index ffd6363..a4b4cc2 100644 --- a/README.md +++ b/README.md @@ -338,12 +338,18 @@ openssl req -x509 -out ./emulator.crt -keyout ./emulator.key -newkey rsa:2048 -n The port for HTTPS must be set using the environment variable [`ASPNETCORE_HTTPS_PORTS`](https://learn.microsoft.com/aspnet/core/security/enforcing-ssl#port-configuration). +The paths for the certificate and key must be set using the environment variables `Kestrel__Certificates__Default__Path` and `Kestrel__Certificates__Default__KeyPath` respectively. + +The certificate and key must be [mounted](https://docs.docker.com/storage/bind-mounts) into the container at the paths that are set above. + ```yaml services: azure-app-configuration-emulator: environment: - ASPNETCORE_HTTP_PORTS=8080 - ASPNETCORE_HTTPS_PORTS=8081 + - Kestrel__Certificates__Default__Path=/usr/local/share/azureappconfigurationemulator/emulator.crt + - Kestrel__Certificates__Default__KeyPath=/usr/local/share/azureappconfigurationemulator/emulator.key image: tnc1997/azure-app-configuration-emulator volumes: - ./emulator.crt:/usr/local/share/azureappconfigurationemulator/emulator.crt:ro diff --git a/setup.iss b/setup.iss new file mode 100644 index 0000000..4ec666c --- /dev/null +++ b/setup.iss @@ -0,0 +1,89 @@ +#define MyAppName "Emulator for Azure App Configuration" +#define MyAppVersion "1.0.0" +#define MyAppPublisher "Thomas Clark" +#define MyAppURL "https://azureappconfigurationemulator.thomasclark.app" +#define MyAppExeName "AzureAppConfigurationEmulator.exe" + +[Setup] +AppId={{7D09D62B-09DF-4C36-8736-96FE3BEE4830} +AppName={#MyAppName} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +AppVersion={#MyAppVersion} +#if Architecture == "arm64" + ArchitecturesAllowed=arm64 +#elif Architecture == "x64" + ArchitecturesAllowed=x64 +#endif +ArchitecturesInstallIn64BitMode=arm64 x64 +DefaultDirName={autopf}\{#MyAppName} +LicenseFile=LICENSE +PrivilegesRequiredOverridesAllowed=dialog +SolidCompression=yes +WizardStyle=modern + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "src\AzureAppConfigurationEmulator\bin\Release\net8.0\win-{#Architecture}\publish\*"; DestDir: "{app}"; Flags: createallsubdirs ignoreversion recursesubdirs + +[Icons] +Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon + +[Run] +Filename: "{tmp}\aspnetcore-runtime.exe"; Parameters: "/install /quiet /norestart"; Check: AspNetCoreRuntimeNeedsInstall +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + +[Code] +var + DownloadPage: TDownloadWizardPage; +function AspNetCoreRuntimeNeedsInstall: Boolean; +var + FileName: String; + Output: AnsiString; + ResultCode: Integer; +begin + Result := True; + FileName := ExpandConstant('{tmp}\dotnet.txt'); + if Exec(ExpandConstant('{cmd}'), '/C dotnet --list-runtimes > "' + FileName + '" 2>&1', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0) then + if LoadStringFromFile(FileName, Output) then + if Pos('Microsoft.AspNetCore.App 8.0', Output) > 0 then + Result := False; +end; +procedure InitializeWizard; +begin + DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil); +end; +function NextButtonClick(CurPageID: Integer): Boolean; +begin + if CurPageID = wpReady then + begin + DownloadPage.Clear; + #if Architecture == "arm64" + DownloadPage.Add('https://download.visualstudio.microsoft.com/download/pr/ee1b10d3-aca1-4ae0-b74a-97bd30fa6d2d/87e7a62e9f5438342b66e673d422cd57/aspnetcore-runtime-8.0.6-win-arm64.exe', 'aspnetcore-runtime.exe', ''); + #elif Architecture == "x64" + DownloadPage.Add('https://download.visualstudio.microsoft.com/download/pr/38b32fc8-8070-4f14-bd52-65505fddc5ff/50e6cf3b7505eee02c3b3db8ea46ffe3/aspnetcore-runtime-8.0.6-win-x64.exe', 'aspnetcore-runtime.exe', ''); + #endif + DownloadPage.Show; + try + try + DownloadPage.Download; + Result := True; + except + if not DownloadPage.AbortedByUser then + SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK); + Result := False; + end; + finally + DownloadPage.Hide; + end; + end else + Result := True; +end; diff --git a/src/AzureAppConfigurationEmulator/Common/HostingExtensions.cs b/src/AzureAppConfigurationEmulator/Common/HostingExtensions.cs index 85f016d..ef58386 100644 --- a/src/AzureAppConfigurationEmulator/Common/HostingExtensions.cs +++ b/src/AzureAppConfigurationEmulator/Common/HostingExtensions.cs @@ -1,46 +1,9 @@ -using System.Security.Cryptography.X509Certificates; using AzureAppConfigurationEmulator.Data; namespace AzureAppConfigurationEmulator.Common; public static class HostingExtensions { - public static string SslCertificatePath { get; } = Environment.OSVersion.Platform switch - { - PlatformID.Win32S => @"C:\ProgramData\Azure App Configuration Emulator\emulator.crt", - PlatformID.Win32Windows => @"C:\ProgramData\Azure App Configuration Emulator\emulator.crt", - PlatformID.Win32NT => @"C:\ProgramData\Azure App Configuration Emulator\emulator.crt", - PlatformID.WinCE => @"C:\ProgramData\Azure App Configuration Emulator\emulator.crt", - PlatformID.Unix => "/usr/local/share/azureappconfigurationemulator/emulator.crt", - PlatformID.MacOSX => "/usr/local/share/azureappconfigurationemulator/emulator.crt", - _ => throw new ArgumentOutOfRangeException() - }; - - public static string SslCertificateKeyPath { get; } = Environment.OSVersion.Platform switch - { - PlatformID.Win32S => @"C:\ProgramData\Azure App Configuration Emulator\emulator.key", - PlatformID.Win32Windows => @"C:\ProgramData\Azure App Configuration Emulator\emulator.key", - PlatformID.Win32NT => @"C:\ProgramData\Azure App Configuration Emulator\emulator.key", - PlatformID.WinCE => @"C:\ProgramData\Azure App Configuration Emulator\emulator.key", - PlatformID.Unix => "/usr/local/share/azureappconfigurationemulator/emulator.key", - PlatformID.MacOSX => "/usr/local/share/azureappconfigurationemulator/emulator.key", - _ => throw new ArgumentOutOfRangeException() - }; - - public static IWebHostBuilder ConfigureKestrel(this IWebHostBuilder builder) - { - return builder.ConfigureKestrel(options => - { - if (File.Exists(SslCertificatePath) && File.Exists(SslCertificateKeyPath)) - { - options.ConfigureHttpsDefaults(options => - { - options.ServerCertificate = X509Certificate2.CreateFromPemFile(SslCertificatePath, SslCertificateKeyPath); - }); - } - }); - } - public static void InitializeDatabase(this IApplicationBuilder app) { using var scope = app.ApplicationServices.GetRequiredService().CreateScope(); diff --git a/src/AzureAppConfigurationEmulator/Data/SqliteDbConnectionFactory.cs b/src/AzureAppConfigurationEmulator/Data/SqliteDbConnectionFactory.cs index e34e970..d18ac35 100644 --- a/src/AzureAppConfigurationEmulator/Data/SqliteDbConnectionFactory.cs +++ b/src/AzureAppConfigurationEmulator/Data/SqliteDbConnectionFactory.cs @@ -9,12 +9,12 @@ public class SqliteDbConnectionFactory(IConfiguration? configuration = null) : I private static string DatabasePath { get; } = Environment.OSVersion.Platform switch { - PlatformID.Win32S => @"C:\ProgramData\Azure App Configuration Emulator\emulator.db", - PlatformID.Win32Windows => @"C:\ProgramData\Azure App Configuration Emulator\emulator.db", - PlatformID.Win32NT => @"C:\ProgramData\Azure App Configuration Emulator\emulator.db", - PlatformID.WinCE => @"C:\ProgramData\Azure App Configuration Emulator\emulator.db", - PlatformID.Unix => "/var/lib/azureappconfigurationemulator/emulator.db", - PlatformID.MacOSX => "/var/lib/azureappconfigurationemulator/emulator.db", + PlatformID.Win32S => Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Thomas Clark", "Emulator for Azure App Configuration", "emulator.db"), + PlatformID.Win32Windows => Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Thomas Clark", "Emulator for Azure App Configuration", "emulator.db"), + PlatformID.Win32NT => Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Thomas Clark", "Emulator for Azure App Configuration", "emulator.db"), + PlatformID.WinCE => Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Thomas Clark", "Emulator for Azure App Configuration", "emulator.db"), + PlatformID.Unix => Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "azureappconfigurationemulator", "emulator.db"), + PlatformID.MacOSX => Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "azureappconfigurationemulator", "emulator.db"), _ => throw new ArgumentOutOfRangeException() }; diff --git a/src/AzureAppConfigurationEmulator/Dockerfile b/src/AzureAppConfigurationEmulator/Dockerfile index 06584d1..7b6521e 100644 --- a/src/AzureAppConfigurationEmulator/Dockerfile +++ b/src/AzureAppConfigurationEmulator/Dockerfile @@ -9,6 +9,7 @@ FROM build AS publish RUN dotnet publish "./src/AzureAppConfigurationEmulator/AzureAppConfigurationEmulator.csproj" --configuration Release --output /app/publish FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final +ENV ConnectionStrings__DefaultConnection="Data Source=/var/lib/azureappconfigurationemulator/emulator.db" WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "AzureAppConfigurationEmulator.dll"] diff --git a/src/AzureAppConfigurationEmulator/Program.cs b/src/AzureAppConfigurationEmulator/Program.cs index 7c4a097..84f0032 100644 --- a/src/AzureAppConfigurationEmulator/Program.cs +++ b/src/AzureAppConfigurationEmulator/Program.cs @@ -87,8 +87,6 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.WebHost.ConfigureKestrel(); - var app = builder.Build(); app.Map("/_explorer", app =>