Skip to content

Commit 357e1b1

Browse files
authored
Report PowerShell 5.x module operation failures instead of success (#5309)
1 parent 36491ef commit 357e1b1

2 files changed

Lines changed: 72 additions & 7 deletions

File tree

src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ namespace UniGetUI.PackageEngine.Managers.PowerShellManager;
77

88
internal sealed class PowerShellPkgOperationHelper : BasePkgOperationHelper
99
{
10+
internal const string ErrorVariableName = "UniGetUIOperationError";
11+
1012
public PowerShellPkgOperationHelper(PowerShell manager)
1113
: base(manager) { }
1214

@@ -53,19 +55,30 @@ OperationType operation
5355
parameters.AddRange(["-RequiredVersion", options.Version]);
5456
}
5557

56-
parameters.AddRange(
57-
operation switch
58-
{
59-
OperationType.Update => options.CustomParameters_Update,
60-
OperationType.Uninstall => options.CustomParameters_Uninstall,
61-
_ => options.CustomParameters_Install,
62-
}
58+
IReadOnlyList<string> customParameters = operation switch
59+
{
60+
OperationType.Update => options.CustomParameters_Update,
61+
OperationType.Uninstall => options.CustomParameters_Uninstall,
62+
_ => options.CustomParameters_Install,
63+
};
64+
65+
bool bindsOwnErrorVariable = customParameters.Any(parameter =>
66+
parameter.StartsWith("-ev", StringComparison.OrdinalIgnoreCase)
67+
|| parameter.StartsWith("-errorv", StringComparison.OrdinalIgnoreCase)
6368
);
6469

70+
if (!bindsOwnErrorVariable)
71+
parameters.AddRange(["-ErrorVariable", ErrorVariableName]);
72+
73+
parameters.AddRange(customParameters);
74+
6575
// Windows PowerShell 5.x defaults to TLS 1.0/1.1, which the PowerShell Gallery rejects; force TLS 1.2 so gallery operations can connect under -NoProfile
6676
if (operation is not OperationType.Uninstall)
6777
parameters.Insert(0, "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;");
6878

79+
if (!bindsOwnErrorVariable)
80+
parameters.Add($";if(${ErrorVariableName}){{exit(1)}}");
81+
6982
return parameters;
7083
}
7184

src/UniGetUI.PackageEngine.Tests/PowerShellManagerTests.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,58 @@ public void GetParameters_UpdateOmitsScope()
9595
Assert.DoesNotContain("-Scope", parameters);
9696
}
9797

98+
[Theory]
99+
[InlineData(OperationType.Install)]
100+
[InlineData(OperationType.Update)]
101+
[InlineData(OperationType.Uninstall)]
102+
public void GetParameters_PropagatesNonTerminatingErrorsToTheExitCode(OperationType operation)
103+
{
104+
var manager = new PowerShell();
105+
var package = BuildInstalledPackage(manager);
106+
107+
var parameters = manager.OperationHelper.GetParameters(package, new InstallOptions(), operation);
108+
109+
var errorVariableIndex = parameters.ToList().IndexOf("-ErrorVariable");
110+
Assert.True(errorVariableIndex >= 0);
111+
Assert.Equal(PowerShellPkgOperationHelper.ErrorVariableName, parameters[errorVariableIndex + 1]);
112+
Assert.Equal(
113+
$";if(${PowerShellPkgOperationHelper.ErrorVariableName}){{exit(1)}}",
114+
parameters[^1]
115+
);
116+
}
117+
118+
[Theory]
119+
[InlineData("-ErrorVariable")]
120+
[InlineData("-ev")]
121+
[InlineData("-errorvariable:mine")]
122+
public void GetParameters_YieldsToACustomErrorVariable(string customParameter)
123+
{
124+
var manager = new PowerShell();
125+
var package = BuildInstalledPackage(manager);
126+
127+
var options = new InstallOptions { CustomParameters_Update = [customParameter, "mine"] };
128+
var parameters = manager.OperationHelper.GetParameters(package, options, OperationType.Update);
129+
130+
Assert.DoesNotContain(PowerShellPkgOperationHelper.ErrorVariableName, parameters);
131+
Assert.DoesNotContain(
132+
$";if(${PowerShellPkgOperationHelper.ErrorVariableName}){{exit(1)}}",
133+
parameters
134+
);
135+
}
136+
137+
[Fact]
138+
public void GetParameters_KeepsCustomParametersBoundToTheCmdlet()
139+
{
140+
var manager = new PowerShell();
141+
var package = BuildInstalledPackage(manager);
142+
143+
var options = new InstallOptions { CustomParameters_Update = ["-Proxy", "http://proxy"] };
144+
var parameters = manager.OperationHelper.GetParameters(package, options, OperationType.Update);
145+
146+
Assert.Equal("-Proxy", parameters[^3]);
147+
Assert.Equal("http://proxy", parameters[^2]);
148+
}
149+
98150
[Fact]
99151
public void Capabilities_ScopeAppliesToInstallOnly()
100152
{

0 commit comments

Comments
 (0)