1+ <#
2+ . SYNOPSIS
3+ Publishes Releases to GitHub
4+ . DESCRIPTION
5+ Publishes a Release to GitHub, if the version does not already exist.
6+ #>
7+ [CmdletBinding (SupportsShouldProcess , ConfirmImpact = ' High' )]
8+ param (
9+ # The package
10+ [Parameter (Mandatory , ValueFromPipeline )]
11+ [IO.Packaging.Package ]
12+ $Package ,
13+
14+ # One or more release asssets. These are files that are attached to the package.
15+ [string []]
16+ $ReleaseAsset ,
17+
18+ # The GitHub Token used to publish the release.
19+ # If there is no GitHubEvent, this is presumed to be a Personal Access Token.
20+ [string ]
21+ $GitHubToken = $env: GH_TOKEN ,
22+
23+ # The GitHubOwner.
24+ # If running in a workflow, this should be automatically detected.
25+ # If running outside of a workflow, this must be provided.
26+ [string ]
27+ $GitHubOwner = $env: GITHUB_OWNER ,
28+
29+ # The GitHub Repository, in the form of `owner/repo`
30+ # If running in a workflow, this should be automatically detected.
31+ # If running outside of a workflow, this must be provided.
32+ [string ]
33+ $GitHubRepository = $env: GITHUB_REPOSITORY
34+ )
35+
36+ # If there is no package version, throw
37+ if (-not $package.Version ) { throw " No Package Version" }
38+
39+ # If the package has no repository
40+ if (-not $package.RelationshipExists (' repository' )) {
41+ throw " Package not related to repository" # throw
42+ }
43+
44+ # Get the git app (as opposed to any git functions)
45+ $gitApp = $ExecutionContext.SessionState.InvokeCommand.GetCommand (' git' , ' application' )
46+ # If we could not get git
47+ if (-not $gitApp ) {
48+ throw " No Git" # throw.
49+ }
50+
51+ # Get the repository remote url
52+ $repositoryUrl = @ (& $gitApp remote)[0 ] |
53+ ForEach-Object {
54+ & $gitApp remote get-url $_
55+ }
56+
57+ # and throw if we could not
58+ if (-not $repositoryUrl ) {
59+ throw " No Repository"
60+ }
61+
62+ # Make sure this package is related to the repository
63+ $packageGitRepo = $package.GetRelationship (' repository' ).TargetUri
64+ if ($packageGitRepo -ne $repositoryUrl ) {
65+ # and throw if that is not the case.
66+ throw " Package unrelated to '$repositoryUrl '"
67+ }
68+
69+
70+ # Get the github event
71+ $gitHubEvent = if ($env: GITHUB_EVENT_PATH ) {
72+ [IO.File ]::ReadAllText($env: GITHUB_EVENT_PATH ) | ConvertFrom-Json
73+ } else { $null }
74+
75+ # Warn about confirmation if we do not have one
76+ if (-not $gitHubEvent ) {
77+ Write-Warning " No github event found, prompting for confirmation"
78+ } else {
79+ # If the event is not a merg, warn and return
80+ if (-not ($gitHubEvent.head_commit.message -match " Merge Pull Request #(?<PRNumber>\d+)" ) -and
81+ (-not $gitHubEvent.psobject.properties [' inputs' ])) {
82+ " ::warning::Pull Request has not merged, skipping github release" | Out-Host
83+ return
84+ }
85+ }
86+
87+ # Find the target version
88+ $targetVersion = " v$ ( $package.Version ) "
89+
90+ # Go get all of our releases
91+ $releasesURL = " https://api.github.com/repos/$GitHubRepository /releases"
92+
93+ # List out our source if we are running in a workflow.
94+ if ($gitHubEvent ) {
95+ " Release URL: $releasesURL " | Out-Host
96+ }
97+
98+ # Go get the releases.
99+ $listOfReleases =
100+ Invoke-RestMethod - Uri $releasesURL - Method Get - Headers @ {
101+ " Accept" = " application/vnd.github.v3+json"
102+ " Authorization" =
103+ if ($gitHubEvent ) {
104+ " Bearer $GitHubToken "
105+ } elseif ($GitHubToken ) {
106+ " Basic $ (
107+ [System.Convert ]::ToBase64String([Text.Encoding ]::ASCII.GetBytes(" :$GitHubToken " ))
108+ ) "
109+ }
110+
111+ }
112+
113+ # and see if ours already exists
114+ $releaseExists = $listOfReleases | Where-Object tag_name -eq $targetVersion
115+
116+ # If it does
117+ if ($releaseExists ) {
118+
119+ if ($gitHubEvent ) {
120+ " ::warning::Release '$ ( $releaseExists.Name ) ' Already Exists" | Out-Host
121+ } else {
122+ Write-Warning " '$ ( $releaseExists.Name ) ' Already Exists"
123+ }
124+
125+ # store this to a variable so that we may potentially add assets.
126+ $releasedIt = $releaseExists
127+ } else {
128+ # If no release exists yet,
129+ # prepare our parameters
130+ $releaseParameters = [Ordered ]@ {
131+ Uri = $releasesURL
132+ Method = ' POST'
133+ Body = [Ordered ]@ {
134+ owner = " $gitHubOwner "
135+ repo = " $GitHubRepository "
136+ tag_name = $targetVersion
137+ name = " $ ( $Package.Identifier ) $ ( $package.Version ) "
138+ body =
139+ if ($env: RELEASENOTES ) {
140+ $env: RELEASENOTES
141+ } elseif ($package.PowerShellManifest.PrivateData.PSData.ReleaseNotes ) {
142+ $package.PowerShellManifest.PrivateData.PSData.ReleaseNotes
143+ } else {
144+ " $ ( $package.Identifier ) $targetVersion "
145+ }
146+ draft =
147+ if ($env: RELEASEISDRAFT ) { [bool ]::Parse($env: RELEASEISDRAFT ) } else { $false }
148+ prerelease =
149+ if ($env: PRERELEASE ) { [bool ]::Parse($env: PRERELEASE ) } else { $false }
150+ }
151+ }
152+
153+ # If -WhatIf was passed, return the release parameters
154+ if ($whatIfPreference ) {
155+ return $releaseParameters
156+ }
157+
158+ # If there is no github event, prompt before releasing.
159+ if (-not $gitHubEvent -and -not $psCmdlet.ShouldProcess (" Release $ ( $releaseParameters.body.name ) " )) {
160+ return
161+ }
162+
163+ # Create the release
164+ $releaseParameters.body = $releaseParameters.body | ConvertTo-Json - Depth 10
165+ $ReleaseHeaders = @ {
166+ " Accept" = " application/vnd.github.v3+json"
167+ " Content-type" = " application/json"
168+ " Authorization" = if ($gitHubEvent ) {
169+ " Bearer $GitHubToken "
170+ } else {
171+ " Basic $ (
172+ [System.Convert ]::ToBase64String([Text.Encoding ]::ASCII.GetBytes(" :$GitHubToken " ))
173+ ) "
174+ }
175+ }
176+
177+ $releasedIt = Invoke-RestMethod @releaseParameters - Headers $releaseHeaders
178+ }
179+
180+ if (-not $releasedIt ) {
181+ throw " Release failed"
182+ } else {
183+ $releasedIt | Out-Host
184+ }
185+
186+
187+
188+ if ($ReleaseAsset ) {
189+ $releaseUploadUrl = $releasedIt.upload_url -replace ' \{.+$'
190+
191+ $filesToRelease =
192+ Get-ChildItem - File - Path $ReleaseAsset - ErrorAction Ignore
193+
194+ $releasedFiles = @ {}
195+ foreach ($file in $filesToRelease ) {
196+ if ($releasedFiles [$file.Name ]) {
197+ Write-Warning " Already attached file $ ( $file.Name ) "
198+ continue
199+ }
200+ else {
201+ # If there is no github event, prompt before attaching.
202+ if (-not $gitHubEvent -and -not $psCmdlet.ShouldProcess (" Attach $ ( $file.name ) " )) {
203+ continue
204+ }
205+ $fileBytes = [IO.File ]::ReadAllBytes($file.FullName )
206+ $releasedFiles [$file.Name ] =
207+ Invoke-RestMethod - Uri " ${releaseUploadUrl} ?name=$ ( $file.Name ) " - Headers @ {
208+ " Accept" = " application/vnd.github+json"
209+ " Authorization" = if ($GitHubEvent ) {
210+ " Bearer $GitHubToken "
211+ } else {
212+ " Basic $ (
213+ [System.Convert ]::ToBase64String([Text.Encoding ]::ASCII.GetBytes(" :$GitHubToken " ))
214+ ) "
215+ }
216+ } - Body $fileBytes - ContentType Application/ octet- stream
217+ $releasedFiles [$file.Name ]
218+ }
219+ }
220+
221+ if ($gitHubEvent ) {
222+ " Attached $ ( $releasedFiles.Count ) file(s) to release" | Out-Host
223+ }
224+ }
0 commit comments