From 50caaccd84a8b4be0999022fab3e1057c1231208 Mon Sep 17 00:00:00 2001 From: Cory Knox Date: Thu, 28 Mar 2024 14:33:59 -0700 Subject: [PATCH 1/7] (#967) Parse Info for Error, Warn, and Fatal Chocolatey Agent runs Chocolatey CLI and reports the results back to Chocolatey GUI. As a result, all of the messages come back as "Info" messages. This adds handling to the GrabErrors method to check Info messages for clues that they're actually `Error`, `Warning`, or `Fatal` messages. --- .../Services/ChocolateyService.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs b/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs index 86058ab6e..7bd532639 100644 --- a/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs +++ b/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs @@ -47,6 +47,7 @@ public class ChocolateyService : IChocolateyService private readonly IConfigService _configService; private GetChocolatey _choco; private string _localAppDataPath = string.Empty; + private const string ErrorRegex = "^\\s*(ERROR|FATAL|WARN)"; #pragma warning disable SA1401 // Fields must be private #pragma warning restore SA1401 // Fields must be private @@ -677,6 +678,13 @@ private static List GetErrors(out Action grabErrors) case LogLevel.Error: case LogLevel.Fatal: errors.Add(m.Message); + break; + case LogLevel.Info: + if (System.Text.RegularExpressions.Regex.IsMatch(m.Message, ErrorRegex)) + { + errors.Add(m.Message); + } + break; } }; From 28155f89d2788e9a23f54ef75024f5c9ac808d35 Mon Sep 17 00:00:00 2001 From: Cory Knox Date: Wed, 3 Apr 2024 08:51:30 -0700 Subject: [PATCH 2/7] (maint) Remove unused pragmas --- .../ChocolateyGui.Common.Windows/Services/ChocolateyService.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs b/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs index 7bd532639..f848f5d9d 100644 --- a/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs +++ b/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs @@ -48,8 +48,6 @@ public class ChocolateyService : IChocolateyService private GetChocolatey _choco; private string _localAppDataPath = string.Empty; private const string ErrorRegex = "^\\s*(ERROR|FATAL|WARN)"; -#pragma warning disable SA1401 // Fields must be private -#pragma warning restore SA1401 // Fields must be private public ChocolateyService(IMapper mapper, IProgressService progressService, IChocolateyConfigSettingsService configSettingsService, IXmlService xmlService, IFileSystem fileSystem, IConfigService configService) { From 600b9f8d15c5f2615874bb06d83dbb46e8992082 Mon Sep 17 00:00:00 2001 From: Cory Knox Date: Mon, 22 Apr 2024 09:02:30 -0700 Subject: [PATCH 3/7] (#996) Create config directory if it doesn't exist If the directory for a LiteDatabase doesn't exist, LiteDatabase will not attempt to create it, and will throw an exception because it can't create the file without the parent directory. This ensures that the folder exists before trying to create the database. --- .../Startup/ChocolateyGuiModule.cs | 15 +++++++-- Source/ChocolateyGui.Common/Hacks.cs | 31 +++++++++++++++++++ .../Startup/ChocolateyGuiCliModule.cs | 15 +++++++-- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs index ec8f01a30..1694ebd0f 100644 --- a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs +++ b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs @@ -148,13 +148,22 @@ protected override void Load(ContainerBuilder builder) var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true"); LiteDatabase globalDatabase; + var globalConfigDirectory = Path.Combine(Bootstrapper.AppDataPath, "Config"); + var globalConfigDatabaseFile = Path.Combine(globalConfigDirectory, "data.db"); + if (Hacks.IsElevated) { - globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true"); + if (!Directory.Exists(globalConfigDirectory)) + { + Directory.CreateDirectory(globalConfigDirectory); + Hacks.LockDirectory(globalConfigDirectory); + } + + globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true"); } else { - if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db"))) + if (!File.Exists(globalConfigDatabaseFile)) { // Since the global configuration database file doesn't exist, we must be running in a state where an administrator user // has never run Chocolatey GUI. In this case, use null, which will mean attempts to use the global database will be ignored. @@ -163,7 +172,7 @@ protected override void Load(ContainerBuilder builder) else { // Since this is a non-administrator user, they should only have read permissions to this database - globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};readonly=true"); + globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};readonly=true"); } } diff --git a/Source/ChocolateyGui.Common/Hacks.cs b/Source/ChocolateyGui.Common/Hacks.cs index 3f147b778..1e32e621d 100644 --- a/Source/ChocolateyGui.Common/Hacks.cs +++ b/Source/ChocolateyGui.Common/Hacks.cs @@ -5,6 +5,9 @@ // // -------------------------------------------------------------------------------------------------------------------- +using System; +using System.IO; +using System.Security.AccessControl; using System.Security.Principal; namespace ChocolateyGui.Common @@ -12,5 +15,33 @@ namespace ChocolateyGui.Common public static class Hacks { public static bool IsElevated => (WindowsIdentity.GetCurrent().Owner?.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid)).GetValueOrDefault(false); + + // TODO: Replace this LockDirectory with calls to DotNetFileSystem's LockDirectory when https://github.com/chocolatey/ChocolateyGUI/issues/1046 is completed. + /// + /// Lock the given directory path to just Administrators being able to write. This method is copied from chocolatey.infrastructure.filesystem.DotNetFileSystem, and should be replaced with that call when the minimum Chocolatey.lib is bumped to 2.2.0 or greater. + /// + /// Directory path to lock down. + public static void LockDirectory(string directoryPath) + { + var permissions = Directory.GetAccessControl(directoryPath); + var rules = permissions.GetAccessRules(includeExplicit: true, includeInherited: true, targetType: typeof(NTAccount)); + + // We first need to remove all rules + foreach (FileSystemAccessRule rule in rules) + { + permissions.RemoveAccessRuleAll(rule); + } + + var bultinAdmins = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Translate(typeof(NTAccount)); + var localsystem = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null).Translate(typeof(NTAccount)); + var builtinUsers = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null).Translate(typeof(NTAccount)); + var inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit; + permissions.SetAccessRule(new FileSystemAccessRule(bultinAdmins, FileSystemRights.FullControl, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow)); + permissions.SetAccessRule(new FileSystemAccessRule(localsystem, FileSystemRights.FullControl, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow)); + permissions.SetAccessRule(new FileSystemAccessRule(builtinUsers, FileSystemRights.ReadAndExecute, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow)); + permissions.SetOwner(bultinAdmins); + permissions.SetAccessRuleProtection(isProtected: true, preserveInheritance: false); + Directory.SetAccessControl(directoryPath, permissions); + } } } \ No newline at end of file diff --git a/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs b/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs index 0dc97e388..215cd3ff5 100644 --- a/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs +++ b/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs @@ -48,13 +48,22 @@ protected override void Load(ContainerBuilder builder) var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true"); LiteDatabase globalDatabase; + var globalConfigDirectory = Path.Combine(Bootstrapper.AppDataPath, "Config"); + var globalConfigDatabaseFile = Path.Combine(globalConfigDirectory, "data.db"); + if (Hacks.IsElevated) { - globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true"); + if (!Directory.Exists(globalConfigDirectory)) + { + Directory.CreateDirectory(globalConfigDirectory); + Hacks.LockDirectory(globalConfigDirectory); + } + + globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true"); } else { - if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db"))) + if (!File.Exists(globalConfigDatabaseFile)) { // Since the global configuration database file doesn't exist, we must be running in a state where an administrator user // has never run Chocolatey GUI. In this case, use null, which will mean attempts to use the global database will be ignored. @@ -63,7 +72,7 @@ protected override void Load(ContainerBuilder builder) else { // Since this is a non-administrator user, they should only have read permissions to this database - globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};readonly=true"); + globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};readonly=true"); } } From 82df61900e9fb44868f0e691e2be13df5f4cd821 Mon Sep 17 00:00:00 2001 From: Gary Ewan Park Date: Fri, 26 Apr 2024 02:42:23 -0700 Subject: [PATCH 4/7] (maint) Remove unnecessary whitespace --- Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs b/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs index 215cd3ff5..8d952ad1d 100644 --- a/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs +++ b/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs @@ -58,7 +58,7 @@ protected override void Load(ContainerBuilder builder) Directory.CreateDirectory(globalConfigDirectory); Hacks.LockDirectory(globalConfigDirectory); } - + globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true"); } else From 0f9d71e2102fdf152788a5c0ab3772610ff59098 Mon Sep 17 00:00:00 2001 From: Gary Ewan Park Date: Fri, 26 Apr 2024 02:52:48 -0700 Subject: [PATCH 5/7] (build) Bump Recipe package to latest version Also change gitHubTokenVariable to gitReleaseManagerTokenVariable to reflect change in chocolatey.cake.recipe. --- recipe.cake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recipe.cake b/recipe.cake index 10b99d3ff..b619ebd9a 100644 --- a/recipe.cake +++ b/recipe.cake @@ -1,4 +1,4 @@ -#load nuget:?package=Chocolatey.Cake.Recipe&version=0.23.0 +#load nuget:?package=Chocolatey.Cake.Recipe&version=0.27.0 /////////////////////////////////////////////////////////////////////////////// // MODULES @@ -13,7 +13,7 @@ if (BuildSystem.IsLocalBuild) { Environment.SetVariableNames( - gitHubTokenVariable: "CHOCOLATEYGUI_GITHUB_PAT", + gitReleaseManagerTokenVariable: "CHOCOLATEYGUI_GITHUB_PAT", transifexApiTokenVariable: "CHOCOLATEYGUI_TRANSIFEX_API_TOKEN" ); } From 06db9594cde8a5570aaae321674f3bef2efd7092 Mon Sep 17 00:00:00 2001 From: choco-sync Date: Mon, 19 Feb 2024 14:59:04 +0000 Subject: [PATCH 6/7] (maint) synced local '.templates/' with remote '.github/GitReleaseManager/.templates/' --- .templates/default/issue-note.sbn | 4 ++-- .templates/default/release-info.sbn | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.templates/default/issue-note.sbn b/.templates/default/issue-note.sbn index 10c10a97d..03dc65196 100644 --- a/.templates/default/issue-note.sbn +++ b/.templates/default/issue-note.sbn @@ -1,6 +1,6 @@ {{ if issue_label == "Bug" || issue_label == "Bug Fix" || issue_label == "Bug Fixes" -}}- Fix - {{ issue.title }} - see [#{{ issue.number }}]({{ issue.html_url }}). +}}- Fix - {{ issue.title }} - see [#{{ issue.public_number }}]({{ issue.html_url }}). {{ else -}}- {{ issue.title }} - see [#{{ issue.number }}]({{ issue.html_url }}). +}}- {{ issue.title }} - see [#{{ issue.public_number }}]({{ issue.html_url }}). {{ end -}} diff --git a/.templates/default/release-info.sbn b/.templates/default/release-info.sbn index 8410ca5ad..2b495d213 100644 --- a/.templates/default/release-info.sbn +++ b/.templates/default/release-info.sbn @@ -1,9 +1,9 @@ {{ if issues.count > 0 if commits.count > 0 -}}As part of this release we had [{{ commits.count }} {{ commits.count | string.pluralize "commit" "commits" }}]({{ commits.html_url }}) which resulted in [{{ issues.count }} {{ issues.count | string.pluralize "issue" "issues" }}]({{ milestone.target.html_url }}?closed=1) being closed. +}}As part of this release we had [{{ commits.count }} {{ commits.count | string.pluralize "commit" "commits" }}]({{ commits.html_url }}) which resulted in [{{ issues.count }} {{ issues.count | string.pluralize "issue" "issues" }}]({{ milestone.target.html_url }}?{{ milestone.query_string }}) being closed. {{ else -}}As part of this release we had [{{ issues.count }} {{ issues.count | string.pluralize "issue" "issues" }}]({{ milestone.target.html_url }}?closed=1) closed. +}}As part of this release we had [{{ issues.count }} {{ issues.count | string.pluralize "issue" "issues" }}]({{ milestone.target.html_url }}?{{ milestone.query_string }}) closed. {{ end else if commits.count > 0 }}As part of this release we had [{{ commits.count }} {{ commits.count | string.pluralize "commit" "commits" }}]({{ commits.html_url }}). From f1dafc6ee9d2ac18040d00b75e9aa5e088109850 Mon Sep 17 00:00:00 2001 From: Gary Ewan Park Date: Fri, 26 Apr 2024 03:15:37 -0700 Subject: [PATCH 7/7] (build) Switch to a PowerShell step The build is failing on the hotfix branch, when it isn't on the develop branch, and this is the only immediate difference between the two branches. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a04018c31..2f700f481 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,6 +35,7 @@ jobs: key: ${{ runner.os }}-tools-${{ hashFiles('recipe.cake') }} - name: Build project + shell: powershell run: | ./build.ps1 --target=CI