Skip to content

Commit 77a18a7

Browse files
authored
Merge pull request #4707 from KoenZomers/GetChangelogFix
Fixed `Get-PnPChangeLog` not returning data
2 parents a55693d + 1d12fbd commit 77a18a7

File tree

3 files changed

+142
-62
lines changed

3 files changed

+142
-62
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
106106
- Fix `Connect-PnPOnline` cmdlet not working with On Prem related cmdlets. [#4622](https://github.com/pnp/powershell/pull/4622)
107107
- Fix `Get\Invoke-PnPSiteTemplate` cmdlet not working in vanity domains. [#4630](https://github.com/pnp/powershell/pull/4630)
108108
- Fixed passing a `Get-PnPRecycleBinItem` result or a GUID to `Restore-PnPRecycleBinItem` not working correctly. [#4667](https://github.com/pnp/powershell/pull/4667)
109+
- Fixed `Get-PnPChangeLog` not returning the changelog [#4707](https://github.com/pnp/powershell/pull/4707)
109110

110111
### Removed
111112

documentation/Get-PnPChangeLog.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ Returns the changelog for PnP PowerShell
1414

1515
## SYNTAX
1616

17+
### Current nightly
1718
```powershell
18-
Get-PnPChangeLog [-Nightly]
19+
Get-PnPChangeLog -Nightly [-Verbose]
20+
```
21+
22+
### Specific version
23+
```powershell
24+
Get-PnPChangeLog [-Version <String>] [-Verbose]
1925
```
2026

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

2430
## EXAMPLES
2531

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

31-
Returns the changelog for the currently released version.
37+
Returns the changelog for the latest released stable version.
3238

3339
### EXAMPLE 2
3440
```powershell
@@ -37,11 +43,32 @@ Get-PnPChangeLog -Nightly
3743

3844
Returns the changelog for the current nightly build.
3945

46+
### EXAMPLE 3
47+
```powershell
48+
Get-PnPChangeLog -Version 2.12.0
49+
```
50+
51+
Returns the changelog for the 2.12.0 release.
52+
4053
## PARAMETERS
4154

4255
### -Nightly
4356
Return the changelog for the nightly build
4457

58+
```yaml
59+
Type: SwitchParameter
60+
Parameter Sets: Current nightly
61+
62+
Required: True
63+
Position: Named
64+
Default value: None
65+
Accept pipeline input: False
66+
Accept wildcard characters: False
67+
```
68+
69+
### -Verbose
70+
When provided, additional debug statements will be shown while executing the cmdlet.
71+
4572
```yaml
4673
Type: SwitchParameter
4774
Parameter Sets: (All)
@@ -53,8 +80,20 @@ Accept pipeline input: False
5380
Accept wildcard characters: False
5481
```
5582
56-
## RELATED LINKS
83+
### -Version
84+
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.
5785
58-
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)
86+
```yaml
87+
Type: SwitchParameter
88+
Parameter Sets: Specific version
5989

90+
Required: False
91+
Position: Named
92+
Default value: Latest stable version
93+
Accept pipeline input: False
94+
Accept wildcard characters: False
95+
```
96+
97+
## RELATED LINKS
6098
99+
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)

src/Commands/Base/GetChangeLog.cs

Lines changed: 97 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,117 @@
11
using System.Management.Automation;
2-
using System.Reflection;
3-
using System.Text.Json;
2+
using System.Net.Http;
3+
using System.Text.RegularExpressions;
44

55
namespace PnP.PowerShell.Commands
66
{
7-
[Cmdlet(VerbsCommon.Get, "PnPChangeLog")]
7+
[Cmdlet(VerbsCommon.Get, "PnPChangeLog", DefaultParameterSetName = ParameterSet_SpecificVersion)]
88
[OutputType(typeof(string))]
9-
public class GetChangeLog : PSCmdlet
9+
public partial class GetChangeLog : PSCmdlet
1010
{
11-
[Parameter(Mandatory = false)]
11+
private const string ParameterSet_Nightly = "Current nightly";
12+
private const string ParameterSet_SpecificVersion = "Specific version";
13+
14+
[Parameter(Mandatory = true, ParameterSetName = ParameterSet_Nightly)]
1215
public SwitchParameter Nightly;
1316

14-
[Parameter(Mandatory = false)]
15-
public System.Version Release;
17+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_SpecificVersion)]
18+
[Alias("Release")]
19+
public System.Version Version;
1620

1721
protected override void ProcessRecord()
1822
{
19-
var client = PnP.Framework.Http.PnPHttpClient.Instance.GetHttpClient();
23+
var client = Framework.Http.PnPHttpClient.Instance.GetHttpClient();
24+
string releaseNotes;
2025

21-
if (MyInvocation.BoundParameters.ContainsKey(nameof(Release)))
26+
if (MyInvocation.BoundParameters.ContainsKey(nameof(Version)))
27+
{
28+
releaseNotes = RetrieveSpecificRelease(client, Version.ToString());
29+
}
30+
else if (Nightly)
2231
{
23-
var url = $"https://api.github.com/repos/pnp/powershell/releases/tags/v{Release.Major}.{Release.Minor}.{Release.Build}";
24-
var response = client.GetAsync(url).GetAwaiter().GetResult();
25-
if (response.IsSuccessStatusCode)
26-
{
27-
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
28-
var jsonElement = JsonSerializer.Deserialize<JsonElement>(content);
29-
if (jsonElement.TryGetProperty("body", out JsonElement bodyElement))
30-
{
31-
WriteObject(bodyElement.GetString());
32-
}
33-
}
32+
releaseNotes = RetrieveSpecificRelease(client, "Current nightly");
3433
}
3534
else
3635
{
37-
var url = "https://raw.githubusercontent.com/pnp/powershell/master/CHANGELOG.md";
38-
if (Nightly)
39-
{
40-
url = "https://raw.githubusercontent.com/pnp/powershell/dev/CHANGELOG.md";
41-
}
42-
var assembly = Assembly.GetExecutingAssembly();
43-
var currentVersion = new SemanticVersion(assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion);
44-
var response = client.GetAsync(url).GetAwaiter().GetResult();
45-
if (response.IsSuccessStatusCode)
46-
{
47-
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
48-
49-
if (Nightly)
50-
{
51-
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);
52-
53-
if (match.Success)
54-
{
55-
WriteObject(match.Groups[1].Value);
56-
}
57-
}
58-
else
59-
{
60-
var currentVersionString = $"{currentVersion.Major}.{currentVersion.Minor}.0";
61-
var previousVersionString = $"{currentVersion.Major}.{currentVersion.Minor - 1}.0";
62-
var match = System.Text.RegularExpressions.Regex.Match(content, $"(## \\[{currentVersionString}\\]\\n(.*)\\n)(## \\[{previousVersionString}]\\n)", System.Text.RegularExpressions.RegexOptions.Singleline);
63-
64-
if (match.Success)
65-
{
66-
WriteObject(match.Groups[1].Value);
67-
}
68-
}
69-
}
70-
else
71-
{
72-
throw new PSInvalidOperationException("Cannot retrieve changelog");
73-
}
36+
releaseNotes = RetrieveLatestStableRelease(client);
37+
}
38+
39+
WriteObject(releaseNotes);
40+
}
41+
42+
/// <summary>
43+
/// Retrieves the changelog regarding the latest stable release from GitHub
44+
/// </summary>
45+
/// <param name="httpClient">HttpClient to use to request the data from GitHub</param>
46+
/// <exception cref="PSInvalidOperationException">Thrown if it is unable to parse the changelog data properly</exception>
47+
/// <returns>The changelog regarding the latest stable release</returns>
48+
private string RetrieveLatestStableRelease(HttpClient httpClient)
49+
{
50+
var url = "https://raw.githubusercontent.com/pnp/powershell/dev/CHANGELOG.md";
51+
52+
WriteVerbose($"Retrieving changelog from {url}");
53+
54+
var response = httpClient.GetAsync(url).GetAwaiter().GetResult();
55+
if (!response.IsSuccessStatusCode)
56+
{
57+
throw new PSInvalidOperationException("Failed to retrieve changelog from GitHub");
58+
}
59+
60+
WriteVerbose("Successfully retrieved changelog from GitHub");
61+
62+
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
63+
64+
var releasedVersions = Regex.Matches(content, @"## \[(?<version>\d+?\.\d+?\.\d+?)]");
65+
if (releasedVersions.Count == 0)
66+
{
67+
throw new PSInvalidOperationException("Failed to identify versions in changelog on GitHub");
68+
}
69+
70+
WriteVerbose($"Found {releasedVersions.Count} released versions in changelog");
71+
WriteVerbose($"Looking for release information on previous stable version {releasedVersions[0].Groups["version"].Value}");
72+
73+
var match = Regex.Match(content, @$"(?<changelog>## \[{releasedVersions[0].Groups["version"].Value.Replace(".", @"\.")}]\n.*?)\n## \[\d+?\.\d+?\.\d+?\]", RegexOptions.Singleline);
74+
75+
if (!match.Success)
76+
{
77+
throw new PSInvalidOperationException($"Failed to identify changelog for version {releasedVersions[0].Groups["version"].Value} on GitHub");
78+
}
79+
80+
return match.Groups["changelog"].Value;
81+
}
82+
83+
/// <summary>
84+
/// Retrieves the changelog regarding a specific release from GitHub
85+
/// </summary>
86+
/// <param name="httpClient">HttpClient to use to request the data from GitHub</param>
87+
/// <exception cref="PSInvalidOperationException">Thrown if it is unable to parse the changelog data properly</exception>
88+
/// <returns>The changelog regarding the specific release</returns>
89+
private string RetrieveSpecificRelease(HttpClient httpClient, string version)
90+
{
91+
var url = "https://raw.githubusercontent.com/pnp/powershell/dev/CHANGELOG.md";
92+
93+
WriteVerbose($"Retrieving changelog from {url}");
94+
95+
var response = httpClient.GetAsync(url).GetAwaiter().GetResult();
96+
if (!response.IsSuccessStatusCode)
97+
{
98+
throw new PSInvalidOperationException("Failed to retrieve changelog from GitHub");
7499
}
100+
101+
WriteVerbose("Successfully retrieved changelog from GitHub");
102+
103+
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
104+
105+
WriteVerbose($"Looking for release information on the {version} release");
106+
107+
var match = Regex.Match(content, @$"(?<changelog>## \[{version}]\n.*?)\n## \[\d+?\.\d+?\.\d+?\]", RegexOptions.Singleline);
108+
109+
if (!match.Success)
110+
{
111+
throw new PSInvalidOperationException($"Failed to identify changelog for the {version} release on GitHub");
112+
}
113+
114+
return match.Groups["changelog"].Value;
75115
}
76116
}
77117
}

0 commit comments

Comments
 (0)