Skip to content

Commit

Permalink
Merge pull request #4707 from KoenZomers/GetChangelogFix
Browse files Browse the repository at this point in the history
Fixed `Get-PnPChangeLog` not returning data
  • Loading branch information
KoenZomers authored Jan 27, 2025
2 parents a55693d + 1d12fbd commit 77a18a7
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 62 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Fix `Connect-PnPOnline` cmdlet not working with On Prem related cmdlets. [#4622](https://github.com/pnp/powershell/pull/4622)
- Fix `Get\Invoke-PnPSiteTemplate` cmdlet not working in vanity domains. [#4630](https://github.com/pnp/powershell/pull/4630)
- Fixed passing a `Get-PnPRecycleBinItem` result or a GUID to `Restore-PnPRecycleBinItem` not working correctly. [#4667](https://github.com/pnp/powershell/pull/4667)
- Fixed `Get-PnPChangeLog` not returning the changelog [#4707](https://github.com/pnp/powershell/pull/4707)

### Removed

Expand Down
49 changes: 44 additions & 5 deletions documentation/Get-PnPChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@ Returns the changelog for PnP PowerShell

## SYNTAX

### Current nightly
```powershell
Get-PnPChangeLog [-Nightly]
Get-PnPChangeLog -Nightly [-Verbose]
```

### Specific version
```powershell
Get-PnPChangeLog [-Version <String>] [-Verbose]
```

## DESCRIPTION
This cmdlets returns the changelog in markdown format. It is retrieved dynamically from GitHub.
This cmdlets returns what has changed in PnP PowerShell in a specific version in markdown format. It is retrieved dynamically from GitHub.

## EXAMPLES

Expand All @@ -28,7 +34,7 @@ This cmdlets returns the changelog in markdown format. It is retrieved dynamical
Get-PnPChangeLog
```

Returns the changelog for the currently released version.
Returns the changelog for the latest released stable version.

### EXAMPLE 2
```powershell
Expand All @@ -37,11 +43,32 @@ Get-PnPChangeLog -Nightly

Returns the changelog for the current nightly build.

### EXAMPLE 3
```powershell
Get-PnPChangeLog -Version 2.12.0
```

Returns the changelog for the 2.12.0 release.

## PARAMETERS

### -Nightly
Return the changelog for the nightly build

```yaml
Type: SwitchParameter
Parameter Sets: Current nightly

Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Verbose
When provided, additional debug statements will be shown while executing the cmdlet.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Expand All @@ -53,8 +80,20 @@ Accept pipeline input: False
Accept wildcard characters: False
```
## RELATED LINKS
### -Version
Return the changelog for a specific version. Be sure to use the correct version number in the format <#>.<#>.<#>, i.e. 2.12.0, otherwise the cmdlet will fail. If omitted, the latest stable version will be returned.
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)
```yaml
Type: SwitchParameter
Parameter Sets: Specific version

Required: False
Position: Named
Default value: Latest stable version
Accept pipeline input: False
Accept wildcard characters: False
```
## RELATED LINKS
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)
154 changes: 97 additions & 57 deletions src/Commands/Base/GetChangeLog.cs
Original file line number Diff line number Diff line change
@@ -1,77 +1,117 @@
using System.Management.Automation;
using System.Reflection;
using System.Text.Json;
using System.Net.Http;
using System.Text.RegularExpressions;

namespace PnP.PowerShell.Commands
{
[Cmdlet(VerbsCommon.Get, "PnPChangeLog")]
[Cmdlet(VerbsCommon.Get, "PnPChangeLog", DefaultParameterSetName = ParameterSet_SpecificVersion)]
[OutputType(typeof(string))]
public class GetChangeLog : PSCmdlet
public partial class GetChangeLog : PSCmdlet
{
[Parameter(Mandatory = false)]
private const string ParameterSet_Nightly = "Current nightly";
private const string ParameterSet_SpecificVersion = "Specific version";

[Parameter(Mandatory = true, ParameterSetName = ParameterSet_Nightly)]
public SwitchParameter Nightly;

[Parameter(Mandatory = false)]
public System.Version Release;
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_SpecificVersion)]
[Alias("Release")]
public System.Version Version;

protected override void ProcessRecord()
{
var client = PnP.Framework.Http.PnPHttpClient.Instance.GetHttpClient();
var client = Framework.Http.PnPHttpClient.Instance.GetHttpClient();
string releaseNotes;

if (MyInvocation.BoundParameters.ContainsKey(nameof(Release)))
if (MyInvocation.BoundParameters.ContainsKey(nameof(Version)))
{
releaseNotes = RetrieveSpecificRelease(client, Version.ToString());
}
else if (Nightly)
{
var url = $"https://api.github.com/repos/pnp/powershell/releases/tags/v{Release.Major}.{Release.Minor}.{Release.Build}";
var response = client.GetAsync(url).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var jsonElement = JsonSerializer.Deserialize<JsonElement>(content);
if (jsonElement.TryGetProperty("body", out JsonElement bodyElement))
{
WriteObject(bodyElement.GetString());
}
}
releaseNotes = RetrieveSpecificRelease(client, "Current nightly");
}
else
{
var url = "https://raw.githubusercontent.com/pnp/powershell/master/CHANGELOG.md";
if (Nightly)
{
url = "https://raw.githubusercontent.com/pnp/powershell/dev/CHANGELOG.md";
}
var assembly = Assembly.GetExecutingAssembly();
var currentVersion = new SemanticVersion(assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion);
var response = client.GetAsync(url).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

if (Nightly)
{
var match = System.Text.RegularExpressions.Regex.Match(content, @"## \[Current Nightly\][\r\n]{1,}(.*?)[\r\n]{1,}## \[[\d\.]{5,}][\r\n]{1,}", System.Text.RegularExpressions.RegexOptions.Singleline);

if (match.Success)
{
WriteObject(match.Groups[1].Value);
}
}
else
{
var currentVersionString = $"{currentVersion.Major}.{currentVersion.Minor}.0";
var previousVersionString = $"{currentVersion.Major}.{currentVersion.Minor - 1}.0";
var match = System.Text.RegularExpressions.Regex.Match(content, $"(## \\[{currentVersionString}\\]\\n(.*)\\n)(## \\[{previousVersionString}]\\n)", System.Text.RegularExpressions.RegexOptions.Singleline);

if (match.Success)
{
WriteObject(match.Groups[1].Value);
}
}
}
else
{
throw new PSInvalidOperationException("Cannot retrieve changelog");
}
releaseNotes = RetrieveLatestStableRelease(client);
}

WriteObject(releaseNotes);
}

/// <summary>
/// Retrieves the changelog regarding the latest stable release from GitHub
/// </summary>
/// <param name="httpClient">HttpClient to use to request the data from GitHub</param>
/// <exception cref="PSInvalidOperationException">Thrown if it is unable to parse the changelog data properly</exception>
/// <returns>The changelog regarding the latest stable release</returns>
private string RetrieveLatestStableRelease(HttpClient httpClient)
{
var url = "https://raw.githubusercontent.com/pnp/powershell/dev/CHANGELOG.md";

WriteVerbose($"Retrieving changelog from {url}");

var response = httpClient.GetAsync(url).GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
throw new PSInvalidOperationException("Failed to retrieve changelog from GitHub");
}

WriteVerbose("Successfully retrieved changelog from GitHub");

var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

var releasedVersions = Regex.Matches(content, @"## \[(?<version>\d+?\.\d+?\.\d+?)]");
if (releasedVersions.Count == 0)
{
throw new PSInvalidOperationException("Failed to identify versions in changelog on GitHub");
}

WriteVerbose($"Found {releasedVersions.Count} released versions in changelog");
WriteVerbose($"Looking for release information on previous stable version {releasedVersions[0].Groups["version"].Value}");

var match = Regex.Match(content, @$"(?<changelog>## \[{releasedVersions[0].Groups["version"].Value.Replace(".", @"\.")}]\n.*?)\n## \[\d+?\.\d+?\.\d+?\]", RegexOptions.Singleline);

if (!match.Success)
{
throw new PSInvalidOperationException($"Failed to identify changelog for version {releasedVersions[0].Groups["version"].Value} on GitHub");
}

return match.Groups["changelog"].Value;
}

/// <summary>
/// Retrieves the changelog regarding a specific release from GitHub
/// </summary>
/// <param name="httpClient">HttpClient to use to request the data from GitHub</param>
/// <exception cref="PSInvalidOperationException">Thrown if it is unable to parse the changelog data properly</exception>
/// <returns>The changelog regarding the specific release</returns>
private string RetrieveSpecificRelease(HttpClient httpClient, string version)
{
var url = "https://raw.githubusercontent.com/pnp/powershell/dev/CHANGELOG.md";

WriteVerbose($"Retrieving changelog from {url}");

var response = httpClient.GetAsync(url).GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
throw new PSInvalidOperationException("Failed to retrieve changelog from GitHub");
}

WriteVerbose("Successfully retrieved changelog from GitHub");

var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

WriteVerbose($"Looking for release information on the {version} release");

var match = Regex.Match(content, @$"(?<changelog>## \[{version}]\n.*?)\n## \[\d+?\.\d+?\.\d+?\]", RegexOptions.Singleline);

if (!match.Success)
{
throw new PSInvalidOperationException($"Failed to identify changelog for the {version} release on GitHub");
}

return match.Groups["changelog"].Value;
}
}
}

0 comments on commit 77a18a7

Please sign in to comment.