diff --git a/appveyor.yml b/appveyor.yml index 2e93d2875..7b0759216 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,54 +1,86 @@ version: 1.1.{build} -image: Visual Studio 2022 branches: only: - main -install: - - choco upgrade chocolatey # Need at least 0.10.8 to avoid packaging error - - dotnet tool update -g Cake.Tool - - dotnet tool update -g checkbinarycompat - - ps: Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -UseBasicParsing -OutFile "$env:temp\dotnet-install.ps1" - - ps: '& $env:temp\dotnet-install.ps1 -Version "8.0.302"' -build_script: -- cmd: >- - dotnet msbuild /p:Configuration=Release /clp:v=m MSBuildStructuredLog.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\dotnetcore\Appveyor.MSBuildLogger.dll" +environment: + matrix: + - job_name: Windows build + appveyor_build_worker_image: Visual Studio 2022 + - job_name: macOS build + appveyor_build_worker_image: macOS - dotnet cake ./build-macos.cake --settings_skippackageversioncheck=true +matrix: + fast_finish: true - checkbinarycompat bin\StructuredLogViewer\Release\net472 +for: + - + matrix: + only: + - job_name: Windows build + init: + - choco upgrade chocolatey + - dotnet tool update -g checkbinarycompat + - ps: Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -UseBasicParsing -OutFile "$env:temp\dotnet-install.ps1" + - ps: '& $env:temp\dotnet-install.ps1 -Version "8.0.302"' + build_script: + - dotnet msbuild /p:Configuration=Release /clp:v=m MSBuildStructuredLog.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\dotnetcore\Appveyor.MSBuildLogger.dll" + - checkbinarycompat bin\StructuredLogViewer\Release\net472 + after_build: + - ps: >- + Compress-Archive ` + "bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogSetup.exe", ` + "bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogViewer*.nupkg", ` + "bin\StructuredLogger\Release\netstandard2.0\StructuredLogger.dll" ` + -DestinationPath "MSBuildStructuredLog-${Env:APPVEYOR_BUILD_VERSION}.zip" + artifacts: + - path: msbuild.binlog + name: MSBuild Log + - path: 'bin\StructuredLogViewer\Release\net472\msbuild-structured-log-viewer*.nupkg' + name: Chocolatey Package + - path: 'bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogSetup.exe' + name: MSBuildStructuredLogSetup.exe + - path: 'bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogViewer*.nupkg' + name: Installer nupkg + - path: 'bin\StructuredLogViewer\Release\net472\Releases\RELEASES' + name: RELEASES + - path: 'bin\StructuredLogger\Release\netstandard2.0\StructuredLogger.dll' + name: StructuredLogger.dll + - path: 'MSBuildStructuredLog-*.zip' + name: Bundle + on_failure: + - appveyor PushArtifact msbuild.binlog + deploy: + - provider: Webhook + url: https://app.signpath.io/API/v1/74f63071-f2aa-46ce-bd8f-1e7cd8774019/Integrations/AppVeyor?ProjectKey=MSBuildStructuredLog&SigningPolicyKey=release-signing + authorization: + secure: WALjHGjvNllt916kBDQ5tSYXGvaKDqymo/jQJoIKwITueSp4LF3jS+9nllR46G8pp2AH+Z6RL1f089XGDOYlfg== -after_build: -- ps: >- - Compress-Archive ` - "bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogSetup.exe", ` - "bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogViewer*.nupkg", ` - "bin\StructuredLogger\Release\netstandard2.0\StructuredLogger.dll" ` - -DestinationPath "MSBuildStructuredLog-${Env:APPVEYOR_BUILD_VERSION}.zip" - -artifacts: -- path: msbuild.binlog - name: MSBuild Log -- path: 'bin\StructuredLogViewer\Release\net472\msbuild-structured-log-viewer*.nupkg' - name: Chocolatey Package -- path: 'bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogSetup.exe' - name: MSBuildStructuredLogSetup.exe -- path: 'bin\StructuredLogViewer\Release\net472\Releases\MSBuildStructuredLogViewer*.nupkg' - name: Installer nupkg -- path: 'bin\StructuredLogViewer\Release\net472\Releases\RELEASES' - name: RELEASES -- path: 'bin\StructuredLogger\Release\netstandard2.0\StructuredLogger.dll' - name: StructuredLogger.dll -- path: 'MSBuildStructuredLog-*.zip' - name: Bundle -- path: 'artifacts\StructuredLogViewer-*.zip' - name: 'Structured Log Viewer macOS app' -on_failure: -- appveyor PushArtifact msbuild.binlog - -deploy: - - provider: Webhook - url: https://app.signpath.io/API/v1/74f63071-f2aa-46ce-bd8f-1e7cd8774019/Integrations/AppVeyor?ProjectKey=MSBuildStructuredLog&SigningPolicyKey=release-signing - authorization: - secure: WALjHGjvNllt916kBDQ5tSYXGvaKDqymo/jQJoIKwITueSp4LF3jS+9nllR46G8pp2AH+Z6RL1f089XGDOYlfg== + - + matrix: + only: + - job_name: macOS build + environment: + APPLE_ID_EMAIL: + secure: RKmcmSlBIe+qymOfMJR9U9Q2axndE5FnQWJrHIm/ZJM= + APPLE_ID_PASSWORD: + secure: Xqa3m49/axGFkH9nr8zZRLgMbFzY3rUUsRCXRxPt4B8= + P12_BASE64: + secure: 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 + P12_PASSWORD: + secure: g9nZcXsjCU8Ogsic6sO45hYJI1sMG/Psw4bes9yknMo= + APPLE_TEAM_ID: + secure: AnEDLgBUDM9+UAdcIOrMLQ== + APPLE_CERT_NAME: + secure: QWdxOY0xIK4XR50AYb77TKCmMd2k00iEBfrYYxzhwM+pDyvSjQXO6Oqg1epfe0KRpZNc+a9cGwCJ8qMyCEQxsA== + init: + - curl -sSL https://dot.net/v1/dotnet-install.sh | /bin/bash -s -- --channel 8.0 + build_script: + - dotnet tool install Cake.Tool --create-manifest-if-needed + - dotnet tool run dotnet-cake ./build-macos.cake --settings_skippackageversioncheck=true + artifacts: + - path: 'artifacts\StructuredLogViewer-*.zip' + name: 'Structured Log Viewer macOS app' + on_failure: + - appveyor PushArtifact msbuild.binlog diff --git a/build-macos.cake b/build-macos.cake index 6994580b1..623c2b684 100644 --- a/build-macos.cake +++ b/build-macos.cake @@ -25,6 +25,12 @@ var netCoreProject = new { }; +var certIsSet = !string.IsNullOrEmpty(EnvironmentVariable("P12_BASE64")); +var certNameIsSet = !string.IsNullOrEmpty(EnvironmentVariable("APPLE_CERT_NAME")); + +var keychainPath = "app-signing.keychain"; +var keychainPassword = Guid.NewGuid().ToString("N"); + Task("Clean") .Does(()=>{ CleanDirectories(buildDirs); @@ -59,18 +65,172 @@ var netCoreProject = new { var outputDir = artifactsDir.Combine(runtime); Information("Publishing: {0}, runtime: {1}", netCoreProject.Name, runtime); - DotNetPublish(netCoreProject.Path, new DotNetPublishSettings { + var settings = new DotNetPublishSettings + { //Framework = netCoreProject.Framework, Configuration = configuration, Runtime = runtime, SelfContained = true, + PublishSingleFile = true, OutputDirectory = outputDir.FullPath - }); + }; + if (configuration == "Release") + { + settings.MSBuildSettings = new DotNetMSBuildSettings() + .WithProperty("DebugType", "None") + .WithProperty("DebugSymbols", "false") + .WithProperty("IncludeSymbolsInSingleFile", "false") + .WithProperty("CopyOutputSymbolsToPublishDirectory", "false"); + } + + DotNetPublish(netCoreProject.Path, settings); } }); +Task("Install-Certificate") + .WithCriteria(certIsSet) + .Does(() => +{ + var p12Base64 = EnvironmentVariable("P12_BASE64")?.Replace("\r", "").Replace("\n", ""); + var p12Password = EnvironmentVariable("P12_PASSWORD"); + + if (string.IsNullOrEmpty(p12Base64)) + { + Error("P12_BASE64 environment variable is not set."); + return; + } + + if (string.IsNullOrEmpty(p12Password)) + { + Error("P12_PASSWORD environment variable is not set."); + return; + } + + Information("Decoding the P12 certificate from base64..."); + + var p12Bytes = Convert.FromBase64String(p12Base64); + var tempP12File = "./certificate.p12"; + + try + { + System.IO.File.WriteAllBytes(tempP12File, p12Bytes); + + Information("Creating temporary keychain..."); + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("create-keychain") + .Append("-p") + .AppendQuoted(keychainPassword) + .AppendQuoted(keychainPath) + }); + + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("set-keychain-settings") + .Append("-lut") + .Append("21600") + .AppendQuoted(keychainPath) + }); + + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("unlock-keychain") + .Append("-p") + .AppendQuoted(keychainPassword) + .AppendQuoted(keychainPath) + }); + + DownloadAndInstallAppleCert("https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer"); + DownloadAndInstallAppleCert("https://www.apple.com/certificateauthority/AppleRootCA-G2.cer"); + DownloadAndInstallAppleCert("https://www.apple.com/certificateauthority/AppleWWDRCAG2.cer"); + + Information("Importing certificate to keychain..."); + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("import") + .AppendQuoted(tempP12File) + .Append("-P") + .AppendQuoted(p12Password) + .Append("-t") + .Append("cert") + // -A allows access for this cert for any app on the machine + // But -T only limits it to specific apps (codesign and security here) + // That's what Apple does for GitHub Actions: + // https://github.com/Apple-Actions/import-codesign-certs/blob/63fff01cd422d4b7b855d40ca1e9d34d2de9427d/src/security.ts#L109-L113 + .Append("-A") + .Append("-T") + .Append("/usr/bin/codesign") + .Append("-T") + .Append("/usr/bin/security") + .Append("-f") + .Append("pkcs12") + .Append("-k") + .AppendQuoted(keychainPath) + }); + + Information("Set keychain partition"); + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("set-key-partition-list") + .Append("-S") + .Append("apple-tool:,apple:") + .Append("-k") + .AppendQuoted(keychainPassword) + .AppendQuoted(keychainPath) + }); + + Information("Update keychains visibility"); + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("list-keychains") + .Append("-d") + .Append("user") + .Append("-s") + .AppendQuoted(keychainPath) + .Append("login.keychain") + }); + + Information("Successfully imported the certificate."); + } + finally + { + System.IO.File.Delete(tempP12File); + + Information("Temporary P12 certificate file deleted."); + } + + void DownloadAndInstallAppleCert(string cert) + { + var fileName = System.IO.Path.GetFileName(cert); + RunToolWithOutput("curl", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("-o") + .AppendQuoted(fileName) + .AppendQuoted(cert) + }); + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("import") + .AppendQuoted(fileName) + .Append("-T") + .Append("/usr/bin/codesign") + .Append("-T") + .Append("/usr/bin/security") + .Append("-k") + .AppendQuoted(keychainPath) + }); + } +}); - Task("Package-Mac") + Task("Create-Bundle") .IsDependentOn("Publish-NetCore") .Does(() => { @@ -83,7 +243,7 @@ var netCoreProject = new { Information("Copying Info.plist"); EnsureDirectoryExists(tempDir.Combine("Contents")); CopyFileToDirectory($"{netCoreAppsRoot}/{netCoreApp}/Info.plist", tempDir.Combine("Contents")); - + // Update versions in Info.plist var plistFile = tempDir.Combine("Contents").CombineWithFilePath("Info.plist"); dynamic plist = DeserializePlist(plistFile); @@ -94,18 +254,119 @@ var netCoreProject = new { Information("Copying App Icons"); EnsureDirectoryExists(tempDir.Combine("Contents/Resources")); CopyFileToDirectory($"{netCoreAppsRoot}/{netCoreApp}/StructuredLogViewer.icns", tempDir.Combine("Contents/Resources")); - + + EnsureDirectoryExists(tempDir.Combine("Contents/Frameworks")); + Information("Copying executables"); MoveDirectory(workingDir, tempDir.Combine("Contents/MacOS")); Information("Finish packaging"); EnsureDirectoryExists(workingDir); MoveDirectory(tempDir, workingDir.Combine($"{macAppName}.app")); + } + }); + + Task("Sign-Bundle") + .WithCriteria(certNameIsSet) + .IsDependentOn("Install-Certificate") + .IsDependentOn("Create-Bundle") + .Does(() => +{ + var runtimeIdentifiers = netCoreProject.Runtimes.Where(r => r.StartsWith("osx")); + var entitlementsFilePath = $"{netCoreAppsRoot}/{netCoreApp}/Entitlements.plist"; + + foreach(var runtime in runtimeIdentifiers) + { + Information($"Starting {runtime} macOS app signing"); + var appBundlePath = artifactsDir.Combine(runtime).Combine($"{macAppName}.app"); + var signingIdentity = EnvironmentVariable("APPLE_CERT_NAME"); + + foreach (var dylib in GetFiles($"{appBundlePath}/**/*.dylib")) + { + Information($"Signing {dylib} library"); + + // Sign the library: + var args = new ProcessArgumentBuilder(); + args.Append("--force"); + args.Append("--sign"); + args.AppendQuoted(signingIdentity); + args.AppendQuoted(dylib.ToString()); + + RunToolWithOutput("codesign", new ProcessSettings + { + Arguments = args.RenderSafe() + }); + } + + // Sign the bundle: + { + Information($"Signing {appBundlePath} bundle"); + + var args = new ProcessArgumentBuilder(); + args.Append("--force"); + args.Append("--timestamp"); + args.Append("--options=runtime"); + args.Append("--entitlements"); + args.AppendQuoted(entitlementsFilePath); + args.Append("--sign"); + args.AppendQuoted(signingIdentity); + args.AppendQuoted(appBundlePath.ToString()); + + RunToolWithOutput("codesign",new ProcessSettings + { + Arguments = args.RenderSafe() + }); + } + } +}); + +Task("Compress-Bundle") + .IsDependentOn("Sign-Bundle") + .Does(() => +{ + var runtimeIdentifiers = netCoreProject.Runtimes.Where(r => r.StartsWith("osx")); + foreach(var runtime in runtimeIdentifiers) + { + Information($"Compressing {runtime} macOS bundle"); + var appBundlePath = artifactsDir.Combine(runtime).Combine($"{macAppName}.app"); var architecture = runtime[(runtime.IndexOf("-")+1)..]; - Zip(workingDir.FullPath, workingDir.CombineWithFilePath($"../{macAppName}-{architecture}.zip")); + var zippedPath = artifactsDir.Combine(runtime).CombineWithFilePath($"../{macAppName}-{architecture}.zip"); + + var args = new ProcessArgumentBuilder(); + args.Append("-c"); + args.Append("-k"); + args.Append("--keepParent"); + args.AppendQuoted(appBundlePath.ToString()); + args.AppendQuoted(zippedPath.ToString()); + + // "Ditto" is absolutely necessary instead of "zip" command. + // Otherwise no symlinks are saved, and notarize process would fail. + RunToolWithOutput("ditto", new ProcessSettings + { + Arguments = args.RenderSafe() + }); } - }); +}); + +Task("Cleanup-After-Sign") + .WithCriteria(certIsSet) + .IsDependentOn("Sign-Bundle") + .Does(() => +{ + RunToolWithOutput("security", new ProcessSettings + { + Arguments = new ProcessArgumentBuilder() + .Append("delete-keychain") + .AppendQuoted(keychainPath) + }); +}); + +Task("Package-Mac") + .IsDependentOn("Create-Bundle") + .IsDependentOn("Sign-Bundle") + .IsDependentOn("Cleanup-After-Sign") + .IsDependentOn("Compress-Bundle"); Task("Default") .IsDependentOn("Restore-NetCore") @@ -113,3 +374,36 @@ var netCoreProject = new { .IsDependentOn("Package-Mac"); RunTarget(target); + + +void RunToolWithOutput( + string toolName, ProcessSettings settings, + bool includeStandardOutput = false, + bool includeStandardError = true) +{ + settings.RedirectStandardOutput = includeStandardOutput; + if (includeStandardOutput) + { + settings.RedirectedStandardOutputHandler = line => + { + if (line is not null) + Information(line); + return line; + }; + } + settings.RedirectStandardError = includeStandardError; + if (includeStandardError) + { + settings.RedirectedStandardErrorHandler = line => + { + if (line is not null) + Error(line); + return line; + }; + } + var exitCode = StartProcess(toolName, settings, out var lines); + if (exitCode != 0) + { + throw new Exception($"The tool exited with code {exitCode}"); + } +} \ No newline at end of file diff --git a/src/StructuredLogViewer.Avalonia/App.xaml b/src/StructuredLogViewer.Avalonia/App.xaml index 57f627933..ba5312f57 100644 --- a/src/StructuredLogViewer.Avalonia/App.xaml +++ b/src/StructuredLogViewer.Avalonia/App.xaml @@ -4,7 +4,8 @@ xmlns:common="clr-namespace:Microsoft.Build.Logging.StructuredLogger;assembly=StructuredLogViewer.Core" xmlns:s="clr-namespace:StructuredLogViewer.Avalonia.Controls;assembly=StructuredLogViewer.Avalonia" x:Class="StructuredLogViewer.Avalonia.App" - RequestedThemeVariant="Light"> + RequestedThemeVariant="Light" + Name="MSBuild Structured Log Viewer"> diff --git a/src/StructuredLogViewer.Avalonia/Entitlements.plist b/src/StructuredLogViewer.Avalonia/Entitlements.plist new file mode 100644 index 000000000..5b67151c0 --- /dev/null +++ b/src/StructuredLogViewer.Avalonia/Entitlements.plist @@ -0,0 +1,26 @@ + + + + + + + com.apple.security.cs.allow-jit + + com.apple.security.automation.apple-events + + com.apple.security.network.client + + + + diff --git a/src/StructuredLogViewer.Avalonia/Info.plist b/src/StructuredLogViewer.Avalonia/Info.plist index 24be1be88..9ee0a4b38 100644 --- a/src/StructuredLogViewer.Avalonia/Info.plist +++ b/src/StructuredLogViewer.Avalonia/Info.plist @@ -2,23 +2,32 @@ - CFBundlePackageType - APPL - CFBundleInfoDictionaryVersion - 6.0 + CFBundleIconFile - StructuredLogViewer + StructuredLogViewer.icns CFBundleName StructuredLogViewer CFBundleExecutable StructuredLogViewer.Avalonia + CFBundleDisplayName + MSBuild Structured Log Viewer CFBundleIdentifier - structuredlogviewer + com.msbuildlog.viewer + CFBundleVersion 0.0.1 CFBundleShortVersionString 0.0.1 + + NSPrincipalClass + NSApplication + CFBundlePackageType + APPL NSHighResolutionCapable True + CFBundleDevelopmentRegion + en + CFBundleInfoDictionaryVersion + 6.0 diff --git a/src/StructuredLogViewer.Avalonia/StructuredLogViewer.Avalonia.csproj b/src/StructuredLogViewer.Avalonia/StructuredLogViewer.Avalonia.csproj index 8e2404846..8cc810476 100644 --- a/src/StructuredLogViewer.Avalonia/StructuredLogViewer.Avalonia.csproj +++ b/src/StructuredLogViewer.Avalonia/StructuredLogViewer.Avalonia.csproj @@ -23,14 +23,11 @@ - - - - PreserveNewest - - - PreserveNewest - + + + + +