@@ -7,120 +7,128 @@ param(
77Set-StrictMode - Version latest
88
99$prefix = ' https?://(www\.)?github.com/'
10- if (-not ($RepoUrl -match " ^$prefix " ))
11- {
12- Write-Warning " Only github.com repositories are currently supported. Given RepoUrl doesn't look like one: $RepoUrl "
10+ if (-not ($RepoUrl -match " ^$prefix ([^/]+)/([^/]+?)(?:\.git)?/?$" )) {
11+ Write-Warning " Only https://github.com repositories are currently supported. Could not parse repository from URL: $RepoUrl "
1312 return
1413}
1514
15+ $repoOwner = $matches [2 ]
16+ $repoName = $matches [3 ]
17+ $apiRepo = " $repoOwner /$repoName "
18+
19+ # Create temporary directory for changelog files
1620$tmpDir = Join-Path ([System.IO.Path ]::GetTempPath()) ([System.Guid ]::NewGuid())
1721New-Item - ItemType Directory $tmpDir | Out-Null
1822
19- try
20- {
21- git clone -- depth 1 $RepoUrl $tmpDir
23+ # Function to try different changelog filenames
24+ function Get-ChangelogContent {
25+ param ( $ref , $filePath )
2226
23- $file = $ (Get-ChildItem - Path $tmpDir | Where-Object { $_.Name -match ' ^changelog(\.md|\.txt|)$' } )
24- if (" $file " -eq ' ' )
25- {
26- Write-Warning " Couldn't find a changelog"
27- return
27+ $changelogNames = @ (' CHANGELOG.md' , ' changelog.md' , ' CHANGELOG.txt' , ' changelog.txt' , ' CHANGELOG' )
28+
29+ foreach ($name in $changelogNames ) {
30+ try {
31+ # Try fetching directly from raw.githubusercontent.com
32+ $rawUrl = " https://raw.githubusercontent.com/$apiRepo /$ref /$name "
33+ $content = Invoke-RestMethod - Uri $rawUrl - Method Get - ErrorAction SilentlyContinue
34+ if ($content ) {
35+ Set-Content - Path $filePath - Value $content - Encoding UTF8
36+ Write-Host " Found changelog for $ref as: $name "
37+ return $true
38+ }
39+ } catch {
40+ # Continue to next filename
41+ }
2842 }
29- elseif ($file -is [Array ])
30- {
31- Write-Warning " Multiple changelogs found: $file "
43+ return $false
44+ }
45+
46+ try {
47+ Write-Host ' Fetching CHANGELOG files for comparison...'
48+
49+ # Fetch old changelog
50+ $oldChangelogPath = Join-Path $tmpDir ' old-changelog.md'
51+ if (-not (Get-ChangelogContent $OldTag $oldChangelogPath )) {
52+ Write-Warning " Could not find changelog at $OldTag "
3253 return
3354 }
34- Write-Host " Found changelog: $file "
35- [string []]$lines = Get-Content $file
36- }
37- finally
38- {
39- Write-Host " Removing $tmpDir "
40- Remove-Item - Recurse - Force - ErrorAction Continue - Path $tmpDir
41- }
4255
43- $startIndex = -1
44- $endIndex = -1
45- $changelog = ' '
46- for ($i = 0 ; $i -lt $lines.Count ; $i ++ )
47- {
48- $line = $lines [$i ]
49-
50- if ($startIndex -lt 0 )
51- {
52- if ($line -match " ^#+ +v?$NewTag \b" )
53- {
54- $startIndex = $i
55- }
56+ # Fetch new changelog
57+ $newChangelogPath = Join-Path $tmpDir ' new-changelog.md'
58+ if (-not (Get-ChangelogContent $NewTag $newChangelogPath )) {
59+ Write-Warning " Could not find changelog at $NewTag "
60+ return
5661 }
57- elseif ($line -match " ^#+ +v?$OldTag \b" )
58- {
59- $endIndex = $i - 1
60- break
62+
63+ Write-Host " Generating changelog diff between $OldTag and $NewTag ..."
64+
65+ # Generate diff using git diff --no-index
66+ $fullDiff = git diff -- no- index $oldChangelogPath $newChangelogPath
67+
68+ # The first lines are diff metadata, skip them
69+ $fullDiff = $fullDiff -split " `n " | Select-Object - Skip 4
70+
71+ if ([string ]::IsNullOrEmpty($fullDiff )) {
72+ Write-Host " No differences found between $OldTag and $NewTag "
73+ return ' '
6174 }
62- }
6375
64- # If the changelog doesn't have a section for the oldTag, stop at the first SemVer that's lower than oldTag.
65- if ($endIndex -lt 0 )
66- {
67- $endIndex = $lines.Count - 1 # fallback, may be overwritten below
68- try
69- {
70- $semverOldTag = [System.Management.Automation.SemanticVersion ]::Parse($OldTag )
71- for ($i = $startIndex ; $i -lt $lines.Count ; $i ++ )
72- {
73- $line = $lines [$i ]
74- if ($line -match ' ^#+ +v?([0-9]+.*)$' )
75- {
76- try
77- {
78- if ($semverOldTag -ge [System.Management.Automation.SemanticVersion ]::Parse($matches [1 ]))
79- {
80- $endIndex = $i - 1
81- break
82- }
76+ # Extract only the added lines (lines starting with + but not ++)
77+ $addedLines = $fullDiff | Where-Object { $_ -match ' ^[+][^+]*' } | ForEach-Object { $_.Substring (1 ) }
78+
79+ if ($addedLines.Count -gt 0 ) {
80+ # Create clean changelog from added lines
81+ $changelog = ($addedLines -join " `n " ).Trim()
82+
83+ # Apply formatting to clean changelog
84+ if ($changelog.Length -gt 0 ) {
85+ # Add header
86+ if (-not ($changelog -match ' ^(##|#) Changelog' )) {
87+ $changelog = " ## Changelog`n`n $changelog "
88+ }
89+
90+ # Increase header level by one for content (not the main header)
91+ $changelog = $changelog -replace ' (^|\n)(#+) ' , ' $1$2# ' -replace ' ^### Changelog' , ' ## Changelog'
92+
93+ # Only add details section if there are deletions or modifications (not just additions)
94+ $hasModifications = $fullDiff | Where-Object { $_ -match ' ^[-]' -and $_ -notmatch ' ^[-]{3}' }
95+ if ($hasModifications ) {
96+ $changelog += " `n`n <details>`n <summary>Full CHANGELOG.md diff</summary>`n`n "
97+ $changelog += ' ```diff' + " `n "
98+ $changelog += $fullDiff -join " `n "
99+ $changelog += " `n " + ' ```' + " `n`n </details>"
100+ }
101+
102+ # Apply standard formatting
103+ # Remove at-mentions.
104+ $changelog = $changelog -replace ' @' , ' '
105+ # Make PR/issue references into links to the original repository (unless they already are links).
106+ $changelog = $changelog -replace ' (?<!\[)#([0-9]+)(?![\]0-9])' , (' [#$1](' + $RepoUrl + ' /issues/$1)' )
107+ # Replace any links pointing to github.com so that the target PRs/Issues don't get na notification.
108+ $changelog = $changelog -replace (' \(' + $prefix ), ' (https://github-redirect.dependabot.com/'
109+
110+ # Limit the changelog length to ~60k to allow for other text in the PR body (total PR limit is 65536 characters).
111+ $limit = 60000
112+ if ($changelog.Length -gt $limit ) {
113+ $oldLength = $changelog.Length
114+ Write-Warning " Truncating changelog because it's $ ( $changelog.Length - $limit ) characters longer than the limit $limit ."
115+ while ($changelog.Length -gt $limit ) {
116+ $changelog = $changelog.Substring (0 , $changelog.LastIndexOf (" `n " ))
83117 }
84- catch {}
118+ $changelog += " `n`n > :warning: **Changelog content truncated by $ ( $oldLength - $changelog .Length ) characters because it was over the limit ( $limit ) and wouldn't fit into PR description.** "
85119 }
120+
121+ return $changelog
86122 }
87123 }
88- catch {}
89- }
90-
91- # Slice changelog lines from startIndex to endIndex.
92- if ($startIndex -ge 0 )
93- {
94- $changelog = ($lines [$startIndex .. $endIndex ] -join " `n " ).Trim()
95- }
96- else
97- {
98- $changelog = ' '
99- }
100- if ($changelog.Length -gt 1 )
101- {
102- $changelog = " # Changelog`n $changelog "
103- # Increase header level by one.
104- $changelog = $changelog -replace ' (^|\n)(#+) ' , ' $1$2# '
105- # Remove at-mentions.
106- $changelog = $changelog -replace ' @' , ' '
107- # Make PR/issue references into links to the original repository (unless they already are links).
108- $changelog = $changelog -replace ' (?<!\[)#([0-9]+)(?![\]0-9])' , (' [#$1](' + $RepoUrl + ' /issues/$1)' )
109- # Replace any links pointing to github.com so that the target PRs/Issues don't get na notification.
110- $changelog = $changelog -replace (' \(' + $prefix ), ' (https://github-redirect.dependabot.com/'
111- }
112124
113- # Limit the changelog length to ~60k to allow for other text in the PR body (total PR limit is 65536 characters).
114- $limit = 60000
115- if ($changelog.Length -gt $limit )
116- {
117- $oldLength = $changelog.Length
118- Write-Warning " Truncating changelog because it's $ ( $changelog.Length - $limit ) characters longer than the limit $limit ."
119- while ($changelog.Length -gt $limit )
120- {
121- $changelog = $changelog.Substring (0 , $changelog.LastIndexOf (" `n " ))
125+ Write-Host " No changelog additions found between $OldTag and $NewTag "
126+ return ' '
127+ } catch {
128+ Write-Warning " Failed to get changelog: $ ( $_.Exception.Message ) "
129+ } finally {
130+ if (Test-Path $tmpDir ) {
131+ Write-Host ' Cleaning up temporary files...'
132+ Remove-Item - Recurse - Force - ErrorAction Continue $tmpDir
122133 }
123- $changelog += " `n`n > :warning: **Changelog content truncated by $ ( $oldLength - $changelog.Length ) characters because it was over the limit ($limit ) and wouldn't fit into PR description.**"
124134}
125-
126- $changelog
0 commit comments