Skip to content

Commit

Permalink
Port PowerShell to .NET Core 3.0 (PowerShell#9597)
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveL-MSFT authored and daxian-dbw committed May 21, 2019
1 parent afa76de commit 29e2147
Show file tree
Hide file tree
Showing 43 changed files with 695 additions and 631 deletions.
7 changes: 4 additions & 3 deletions PowerShell.Common.props
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
Tracking Issue https://github.com/dotnet/sdk/issues/1557
-->
<PackageVersion>$(PSCoreBuildVersion)</PackageVersion>
<ApplicationIcon Condition="$(ProductVersion.Contains('preview'))">..\..\assets\Powershell_av_colors.ico</ApplicationIcon>
<ApplicationIcon Condition="!$(ProductVersion.Contains('preview'))">..\..\assets\Powershell_black.ico</ApplicationIcon>

</PropertyGroup>

Expand Down Expand Up @@ -93,9 +95,8 @@
<Company>Microsoft Corporation</Company>
<Copyright>(c) Microsoft Corporation. All rights reserved.</Copyright>

<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeFrameworkVersion>2.1.8</RuntimeFrameworkVersion>
<LangVersion>Latest</LangVersion>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>8.0</LangVersion>

<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Expand Down
916 changes: 481 additions & 435 deletions assets/files.wxs

Large diffs are not rendered by default.

72 changes: 8 additions & 64 deletions build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# On Windows paths is separated by semicolon
$script:TestModulePathSeparator = [System.IO.Path]::PathSeparator

$dotnetCLIChannel = "release"
$dotnetCLIChannel = 'preview' # TODO: Change this to 'release' once .Net Core 3.0 goes RTM
$dotnetCLIRequiredVersion = $(Get-Content $PSScriptRoot/global.json | ConvertFrom-Json).Sdk.Version

# Track if tags have been sync'ed
Expand Down Expand Up @@ -410,7 +410,7 @@ Fix steps:
Pop-Location
}

# publish netcoreapp2.1 reference assemblies
# publish reference assemblies
try {
Push-Location "$PSScriptRoot/src/TypeCatalogGen"
$refAssemblies = Get-Content -Path $incFileName | Where-Object { $_ -like "*microsoft.netcore.app*" } | ForEach-Object { $_.TrimEnd(';') }
Expand Down Expand Up @@ -449,51 +449,6 @@ Fix steps:
}
}

if ($Environment.IsWindows) {
## need RCEdit to modify the binaries embedded resources
$rcedit = "~/.rcedit/rcedit-x64.exe"
if (-not (Test-Path -Type Leaf $rcedit)) {
$rcedit = Get-Command "rcedit-x64.exe" -CommandType Application -ErrorAction Ignore | Select-Object -First 1 | ForEach-Object Name
}
if (-not $rcedit) {
throw "RCEdit is required to modify pwsh.exe resources, please run 'Start-PSBootStrap' to install"
}

$ReleaseVersion = ""
if ($ReleaseTagToUse) {
$ReleaseVersion = $ReleaseTagToUse
} else {
$ReleaseVersion = (Get-PSCommitId -WarningAction SilentlyContinue) -replace '^v'
}
# in VSCode, depending on where you started it from, the git commit id may be empty so provide a default value
if (!$ReleaseVersion) {
$ReleaseVersion = "6.0.0"
$fileVersion = "6.0.0"
} else {
$fileVersion = $ReleaseVersion.Split("-")[0]
}

# in VSCode, the build output folder doesn't include the name of the exe so we have to add it for rcedit
$pwshPath = $Options.Output
if (!$pwshPath.EndsWith("pwsh.exe")) {
$pwshPath = Join-Path $Options.Output "pwsh.exe"
}

if (Test-IsPreview $ReleaseVersion) {
$iconPath = "$PSScriptRoot\assets\Powershell_av_colors.ico"
} else {
$iconPath = "$PSScriptRoot\assets\Powershell_black.ico"
}

# fxdependent package does not have an executable to set iconPath etc.
if ($Options.Runtime -ne 'fxdependent') {
Start-NativeExecution { & $rcedit $pwshPath --set-icon $iconPath `
--set-file-version $fileVersion --set-product-version $ReleaseVersion --set-version-string "ProductName" "PowerShell 7" `
--set-version-string "LegalCopyright" "(C) Microsoft Corporation. All Rights Reserved." `
--application-manifest "$PSScriptRoot\assets\pwsh.manifest" } | Write-Verbose
}
}

# download modules from powershell gallery.
# - PowerShellGet, PackageManagement, Microsoft.PowerShell.Archive
if ($PSModuleRestore) {
Expand Down Expand Up @@ -617,8 +572,8 @@ function New-PSOptions {
[ValidateSet("Debug", "Release", "CodeCoverage", '')]
[string]$Configuration,

[ValidateSet("netcoreapp2.1")]
[string]$Framework,
[ValidateSet("netcoreapp3.0")]
[string]$Framework = "netcoreapp3.0",

# These are duplicated from Start-PSBuild
# We do not use ValidateScript since we want tab completion
Expand Down Expand Up @@ -656,6 +611,7 @@ function New-PSOptions {
}

Write-Verbose "Using configuration '$Configuration'"
Write-Verbose "Using framework '$Framework'"

if (-not $Runtime) {
if ($Environment.IsLinux) {
Expand Down Expand Up @@ -1741,19 +1697,6 @@ function Start-PSBootstrap {
$psInstallFile = [System.IO.Path]::Combine($PSScriptRoot, "tools", "install-powershell.ps1")
& $psInstallFile -AddToPath
}

## need RCEdit to modify the binaries embedded resources
if (-not (Test-Path "~/.rcedit/rcedit-x64.exe"))
{
Write-Log "Install RCEdit for modifying exe resources"
$rceditUrl = "https://github.com/electron/rcedit/releases/download/v1.0.0/rcedit-x64.exe"
New-Item -Path "~/.rcedit" -Type Directory -Force > $null

## need to specify TLS version 1.2 since GitHub API requires it
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

Invoke-WebRequest -OutFile "~/.rcedit/rcedit-x64.exe" -Uri $rceditUrl
}
}
} finally {
Pop-Location
Expand Down Expand Up @@ -1854,12 +1797,13 @@ function Start-TypeGen
<Target Name="_GetDependencies"
DependsOnTargets="ResolveAssemblyReferencesDesignTime">
<ItemGroup>
<_RefAssemblyPath Include="%(_ReferencesFromRAR.HintPath)%3B" Condition=" '%(_ReferencesFromRAR.NuGetPackageId)' != 'Microsoft.Management.Infrastructure' "/>
<_RefAssemblyPath Include="%(_ReferencesFromRAR.OriginalItemSpec)%3B" Condition=" '%(_ReferencesFromRAR.NuGetPackageId)' != 'Microsoft.Management.Infrastructure' "/>
</ItemGroup>
<WriteLinesToFile File="$(_DependencyFile)" Lines="@(_RefAssemblyPath)" Overwrite="true" />
</Target>
</Project>
'@
New-Item -ItemType Directory -Path (Split-Path -Path $GetDependenciesTargetPath -Parent) -Force > $null
Set-Content -Path $GetDependenciesTargetPath -Value $GetDependenciesTargetValue -Force -Encoding Ascii

Push-Location "$PSScriptRoot/src/Microsoft.PowerShell.SDK"
Expand Down Expand Up @@ -2317,7 +2261,7 @@ function Copy-PSGalleryModules
Remove-Item -Force -ErrorAction Ignore -Recurse "$Destination/$name"
New-Item -Path $dest -ItemType Directory -Force -ErrorAction Stop > $null
# Exclude files/folders that are not needed. The fullclr folder is coming from the PackageManagement module
$dontCopy = '*.nupkg', '*.nupkg.sha512', '*.nuspec', 'System.Runtime.InteropServices.RuntimeInformation.dll', 'fullclr'
$dontCopy = '*.nupkg', '*.nupkg.metadata', '*.nupkg.sha512', '*.nuspec', 'System.Runtime.InteropServices.RuntimeInformation.dll', 'fullclr'
Copy-Item -Exclude $dontCopy -Recurse $src/* $dest
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/building/linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Start-PSBuild
Congratulations! If everything went right, PowerShell is now built.
The `Start-PSBuild` script will output the location of the executable:

`./src/powershell-unix/bin/Debug/netcoreapp2.1/linux-x64/publish/pwsh`.
`./src/powershell-unix/bin/Debug/netcoreapp3.0/linux-x64/publish/pwsh`.

You should now be running the PowerShell Core that you just built, if your run the above executable.
You can run our cross-platform Pester tests with `Start-PSPester`, and our xUnit tests with `Start-PSxUnit`.
2 changes: 1 addition & 1 deletion docs/building/macos.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ We cannot do this for you in the build module due to #[847][].

Start a PowerShell session by running `pwsh`, and then use `Start-PSBuild` from the module.

After building, PowerShell will be at `./src/powershell-unix/bin/Debug/netcoreapp2.1/osx-x64/publish/pwsh`.
After building, PowerShell will be at `./src/powershell-unix/bin/Debug/netcoreapp3.0/osx-x64/publish/pwsh`.
4 changes: 2 additions & 2 deletions docs/building/windows-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ Import-Module ./build.psm1
Start-PSBuild
```

Congratulations! If everything went right, PowerShell is now built and executable as `./src/powershell-win-core/bin/Debug/netcoreapp2.1/win7-x64/publish/pwsh.exe`.
Congratulations! If everything went right, PowerShell is now built and executable as `./src/powershell-win-core/bin/Debug/netcoreapp3.0/win7-x64/publish/pwsh.exe`.

This location is of the form `./[project]/bin/[configuration]/[framework]/[rid]/publish/[binary name]`,
and our project is `powershell`, configuration is `Debug` by default,
framework is `netcoreapp2.1`, runtime identifier is `win7-x64` by default,
framework is `netcoreapp3.0`, runtime identifier is `win7-x64` by default,
and binary name is `pwsh`.
The function `Get-PSOutput` will return the path to the executable;
thus you can execute the development copy via `& (Get-PSOutput)`.
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "2.1.504"
"version": "3.0.100-preview5-011568"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ private void LoadAssemblies(IEnumerable<string> assemblies)
/// </summary>
private static IEnumerable<PortableExecutableReference> InitDefaultRefAssemblies()
{
// netcoreapp2.1 currently comes with 144 reference assemblies (maybe more in future), so we use a capacity of '150'.
// netcoreapp3.0 currently comes with 148 reference assemblies (maybe more in future), so we use a capacity of '150'.
var defaultRefAssemblies = new List<PortableExecutableReference>(150);

foreach (string file in Directory.EnumerateFiles(s_netcoreAppRefFolder, "*.dll", SearchOption.TopDirectoryOnly))
Expand Down
3 changes: 2 additions & 1 deletion src/ResGen/ResGen.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

<PropertyGroup>
<Description>Generates C# typed bindings for .resx files</Description>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AssemblyName>resgen</AssemblyName>
<OutputType>Exe</OutputType>
<TieredCompilation>true</TieredCompilation>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
<RuntimeIdentifiers>win7-x86;win7-x64;osx-x64;linux-x64</RuntimeIdentifiers>
</PropertyGroup>

Expand Down
19 changes: 15 additions & 4 deletions src/System.Management.Automation/engine/PSVersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public class PSVersionInfo
private static Version s_psV4Version = new Version(4, 0);
private static Version s_psV5Version = new Version(5, 0);
private static Version s_psV51Version = new Version(5, 1, NTVerpVars.PRODUCTBUILD, NTVerpVars.PRODUCTBUILD_QFE);
private static SemanticVersion s_psV6Version;
private static SemanticVersion s_psV6Version = new SemanticVersion(6, 0, 0, null, null);
private static SemanticVersion s_psV7Version;

/// <summary>
/// A constant to track current PowerShell Edition.
Expand Down Expand Up @@ -99,12 +100,12 @@ static PSVersionInfo()
rawGitCommitId = mainVersion;
}

s_psV6Version = new SemanticVersion(mainVersion);
s_psV7Version = new SemanticVersion(mainVersion);

s_psVersionTable[PSVersionInfo.PSVersionName] = s_psV6Version;
s_psVersionTable[PSVersionInfo.PSVersionName] = s_psV7Version;
s_psVersionTable[PSVersionInfo.PSEditionName] = PSEditionValue;
s_psVersionTable[PSGitCommitIdName] = rawGitCommitId;
s_psVersionTable[PSCompatibleVersionsName] = new Version[] { s_psV1Version, s_psV2Version, s_psV3Version, s_psV4Version, s_psV5Version, s_psV51Version, s_psV6Version };
s_psVersionTable[PSCompatibleVersionsName] = new Version[] { s_psV1Version, s_psV2Version, s_psV3Version, s_psV4Version, s_psV5Version, s_psV51Version, s_psV6Version, s_psV7Version };
s_psVersionTable[PSVersionInfo.SerializationVersionName] = new Version(InternalSerializer.DefaultVersion);
s_psVersionTable[PSVersionInfo.PSRemotingProtocolVersionName] = RemotingConstants.ProtocolVersion;
s_psVersionTable[PSVersionInfo.WSManStackVersionName] = GetWSManStackVersion();
Expand Down Expand Up @@ -271,6 +272,11 @@ internal static string FeatureVersionString

internal static bool IsValidPSVersion(Version version)
{
if (version.Major == s_psV7Version.Major)
{
return version.Minor == s_psV7Version.Minor;
}

if (version.Major == s_psV6Version.Major)
{
return version.Minor == s_psV6Version.Minor;
Expand Down Expand Up @@ -321,6 +327,11 @@ internal static SemanticVersion PSV6Version
get { return s_psV6Version; }
}

internal static SemanticVersion PSV7Version
{
get { return s_psV7Version; }
}

#endregion
}

Expand Down
2 changes: 0 additions & 2 deletions src/System.Management.Automation/engine/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1182,8 +1182,6 @@ internal static bool IsReservedDeviceName(string destinationPath)
string compareName = Path.GetFileName(destinationPath);
string noExtensionCompareName = Path.GetFileNameWithoutExtension(destinationPath);

// See if it's the correct length. If it's shorter than CON, AUX, etc, it can't be a device name.
// Likewise, if it's longer than 'CLOCK$', it can't be a device name.
if (((compareName.Length < 3) || (compareName.Length > 6)) &&
((noExtensionCompareName.Length < 3) || (noExtensionCompareName.Length > 6)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ protected string MakePath(string parent, string child, bool childIsLeaf)
// If the parent is empty but the child is not, return the
// child

result = child.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);
result = NormalizePath(child);
}
else if (!string.IsNullOrEmpty(parent) &&
string.IsNullOrEmpty(child))
Expand Down Expand Up @@ -369,8 +369,8 @@ protected string MakePath(string parent, string child, bool childIsLeaf)
// Normalize the path so that only the default path separator is used as a
// separator even if the user types the alternate slash.

parent = parent.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);
child = child.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);
parent = NormalizePath(parent);
child = NormalizePath(child);
}

// Joins the paths
Expand Down
3 changes: 2 additions & 1 deletion src/TypeCatalogGen/TypeCatalogGen.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

<PropertyGroup>
<Description>Generates CorePsTypeCatalog.cs given powershell.inc</Description>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AssemblyName>TypeCatalogGen</AssemblyName>
<OutputType>Exe</OutputType>
<TieredCompilation>true</TieredCompilation>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
<RuntimeIdentifiers>win7-x86;win7-x64;osx-x64;linux-x64</RuntimeIdentifiers>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion src/powershell-native/Install-PowerShellRemoting.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function Register-WinRmPlugin
SDKVersion="2" XmlRenderingType="text" Enabled="True" OutputBufferingMode="Block" ProcessIdleTimeoutSec="0" Architecture="{2}"
UseSharedProcess="false" RunAsUser="" RunAsPassword="" AutoRestart="false">
<InitializationParameters>
<Param Name="PSVersion" Value="6.0"/>
<Param Name="PSVersion" Value="7.0"/>
</InitializationParameters>
<Resources>
<Resource ResourceUri="http://schemas.microsoft.com/powershell/{0}" SupportsOptions="true" ExactMatch="true">
Expand Down
1 change: 1 addition & 0 deletions src/powershell-unix/powershell-unix.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<AssemblyName>pwsh</AssemblyName>
<OutputType>Exe</OutputType>
<TieredCompilation>true</TieredCompilation>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
<RuntimeIdentifiers>linux-x64;osx-x64;</RuntimeIdentifiers>
</PropertyGroup>

Expand Down
11 changes: 10 additions & 1 deletion src/powershell-win-core/powershell-win-core.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Project ToolsVersion="15.0">
<Import Project="..\..\PowerShell.Common.props" />

<PropertyGroup>
<Description>PowerShell on Windows top-level project</Description>
<AssemblyName>pwsh</AssemblyName>
<OutputType>Exe</OutputType>
<TieredCompilation>true</TieredCompilation>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
<RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
<RootNamespace>Microsoft.PowerShell</RootNamespace>
<ApplicationManifest>..\..\assets\pwsh.manifest</ApplicationManifest>
</PropertyGroup>

<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" Condition="'$(RuntimeIdentifier)' == 'win-arm' or '$(RuntimeIdentifier)' == 'win-arm64'" />
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" Condition="'$(RuntimeIdentifier)' == 'win-arm' or '$(RuntimeIdentifier)' == 'win-arm64'" />

<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.WindowsDesktop" Condition="'$(RuntimeIdentifier)' != 'win-arm' and '$(RuntimeIdentifier)' != 'win-arm64'" />
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.WindowsDesktop" Condition="'$(RuntimeIdentifier)' != 'win-arm' and '$(RuntimeIdentifier)' != 'win-arm64'" />

<ItemGroup>
<Compile Include="..\powershell\Program.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<Content Include="..\System.Management.Automation\powershell.config.json">
Expand Down
5 changes: 2 additions & 3 deletions test/Test.Common.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
<Company>Microsoft Corporation</Company>
<Copyright>(c) Microsoft Corporation. All rights reserved.</Copyright>

<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeFrameworkVersion>2.1.8</RuntimeFrameworkVersion>
<LangVersion>Latest</LangVersion>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>8.0</LangVersion>

<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Expand Down
2 changes: 1 addition & 1 deletion test/hosting/hosting.tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="XunitXml.TestLogger" Version="2.0.0" />
<!-- The version of Microsoft.PowerShell.SDK should be the version we are releasing, so the tests use the correct SDK before publishing to NuGet.org -->
<PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.0-rc.1" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.0" />
<PackageReference Include="Xunit.SkippableFact" Version="1.3.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
Expand Down
11 changes: 8 additions & 3 deletions test/powershell/Host/ConsoleHost.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -824,9 +824,14 @@ Describe "Console host api tests" -Tag CI {
Describe "Pwsh exe resources tests" -Tag CI {
It "Resource strings are embedded in the executable" -Skip:(!$IsWindows) {
$pwsh = Get-Item -Path "$PSHOME\pwsh.exe"
$pwsh.VersionInfo.FileVersion | Should -BeExactly $PSVersionTable.PSVersion.ToString().Split("-")[0]
$pwsh.VersionInfo.ProductVersion.Replace("-dirty","") | Should -BeExactly $PSVersionTable.GitCommitId
$pwsh.VersionInfo.ProductName | Should -BeExactly "PowerShell 7"
$pwsh.VersionInfo.FileVersion | Should -Match $PSVersionTable.PSVersion.ToString().Split("-")[0]
$productVersion = $pwsh.VersionInfo.ProductVersion.Replace("-dirty","").Replace(" Commits: ","-").Replace(" SHA: ","-g")
if ($PSVersionTable.GitCommitId.Contains("-g")) {
$productVersion | Should -BeExactly $PSVersionTable.GitCommitId
} else {
$productVersion | Should -Match $PSVersionTable.GitCommitId
}
$pwsh.VersionInfo.ProductName | Should -BeExactly "PowerShell"
}

It "Manifest contains compatibility section" -Skip:(!$IsWindows) {
Expand Down
2 changes: 1 addition & 1 deletion test/powershell/Host/PSVersionTable.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Describe "PSVersionTable" -Tags "CI" {
$PSVersionTable.PSVersion | Should -BeOfType "System.Management.Automation.SemanticVersion"
$PSVersionTable.PSVersion | Should -BeExactly $expectedPSVersion
$PSVersionTable.PSVersion | Should -Match $expectedVersionPattern
$PSVersionTable.PSVersion.Major | Should -Be 6
$PSVersionTable.PSVersion.Major | Should -Be 7
}

It "GitCommitId property" {
Expand Down
Loading

0 comments on commit 29e2147

Please sign in to comment.