Skip to content

Commit 2446afd

Browse files
spetersenmsFreddy Kristiansen
andauthored
Publish to Environment from PR (#1441)
Adds support to run the Publish to Environment from a PR by passing a string like "PR_x" in the artifact version input. A PR with id x will be found, and artifacts from latest successful build in that PR will be used if it exist. --------- Co-authored-by: Freddy Kristiansen <[email protected]>
1 parent 7ecc53d commit 2446afd

File tree

10 files changed

+477
-14
lines changed

10 files changed

+477
-14
lines changed

Actions/Deploy/Deploy.ps1

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
Param(
2+
[Parameter(HelpMessage = "The GitHub token running the action", Mandatory = $false)]
3+
[string] $token,
24
[Parameter(HelpMessage = "Name of environment to deploy to", Mandatory = $true)]
35
[string] $environmentName,
46
[Parameter(HelpMessage = "Path to the downloaded artifacts to deploy", Mandatory = $true)]
@@ -7,7 +9,9 @@ Param(
79
[ValidateSet('CD','Publish')]
810
[string] $type = "CD",
911
[Parameter(HelpMessage = "The settings for all Deployment Environments", Mandatory = $true)]
10-
[string] $deploymentEnvironmentsJson
12+
[string] $deploymentEnvironmentsJson,
13+
[Parameter(HelpMessage = "Artifacts version. Used to check if this is a deployment from a PR", Mandatory = $false)]
14+
[string] $artifactsVersion = ''
1115
)
1216

1317
function CheckIfAppNeedsInstallOrUpgrade {
@@ -114,7 +118,7 @@ function InstallUnknownDependencies {
114118
$installedApps = Get-BcInstalledExtensions -bcAuthContext $bcAuthContext -environment $environment | Where-Object { $_.isInstalled }
115119
# Run through all apps and install or upgrade AppSource apps first (and collect PTEs)
116120
foreach($app in $apps) {
117-
#The output of Sort-AppFilesByDependencies is in the format of "AppId:AppName"
121+
# The output of Sort-AppFilesByDependencies is in the format of "AppId:AppName"
118122
$appId, $appName = $app.Split(':')
119123
$appVersion = ""
120124
if ($appName -match "_(\d+\.\d+\.\d+\.\d+)\.app$") {
@@ -123,7 +127,7 @@ function InstallUnknownDependencies {
123127
Write-Host "Version not found or incorrect format for unknown dependency $app"
124128
continue
125129
}
126-
#Create a fake appJson with the properties used in CheckIfAppNeedsInstallOrUpgrade
130+
# Create a fake appJson with the properties used in CheckIfAppNeedsInstallOrUpgrade
127131
$appJson = @{
128132
"name" = $appName
129133
"id" = $appId
@@ -150,6 +154,7 @@ function InstallUnknownDependencies {
150154
}
151155
}
152156

157+
Import-Module (Join-Path -Path $PSScriptRoot "Deploy.psm1")
153158
. (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve)
154159
DownloadAndImportBcContainerHelper
155160

@@ -192,21 +197,32 @@ $artifactsFolder = Join-Path $ENV:GITHUB_WORKSPACE $artifactsFolder
192197
if (Test-Path $artifactsFolder -PathType Container) {
193198
$deploymentSettings.Projects.Split(',') | ForEach-Object {
194199
$project = $_.Replace('\','_').Replace('/','_')
200+
$artifactVersionFilter = '*.*.*.*'
195201
$refname = "$ENV:GITHUB_REF_NAME".Replace('/','_')
202+
# Artifacts from PRs are named differently - project-ref-Apps-PRx-date
203+
if ($artifactsVersion -like "PR_*") {
204+
$prId = $artifactsVersion.SubString(3)
205+
$intId = 0
206+
if (!([Int]::TryParse($prId, [ref] $intId))) {
207+
throw "Invalid PR id: $prId"
208+
}
209+
$artifactVersionFilter = "PR$prId-*"
210+
$refname = GetHeadRefFromPRId -repository $ENV:GITHUB_REPOSITORY -prId $prId -token $token
211+
}
196212
Write-Host "project '$project'"
197213

198214
$allApps = @()
199-
$projectApps = @((Get-ChildItem -Path $artifactsFolder -Filter "$project-$refname-$($buildMode)Apps-*.*.*.*") | ForEach-Object { $_.FullName })
215+
$projectApps = @((Get-ChildItem -Path $artifactsFolder -Filter "$project-$refname-$($buildMode)Apps-$artifactVersionFilter") | ForEach-Object { $_.FullName })
200216
$projectTestApps = @()
201217
if ($deploymentSettings.includeTestAppsInSandboxEnvironment) {
202218
Write-Host "Including test apps for deployment"
203-
$projectTestApps = @((Get-ChildItem -Path $artifactsFolder -Filter "$project-$refname-$($buildMode)TestApps-*.*.*.*") | ForEach-Object { $_.FullName })
219+
$projectTestApps = @((Get-ChildItem -Path $artifactsFolder -Filter "$project-$refname-$($buildMode)TestApps-$artifactVersionFilter") | ForEach-Object { $_.FullName })
204220
}
205221
if ($deploymentSettings.excludeAppIds) {
206222
Write-Host "Excluding apps with ids $($deploymentSettings.excludeAppIds) from deployment"
207223
}
208224
if ($deploymentSettings.DependencyInstallMode -ne "ignore") {
209-
$dependencies += @((Get-ChildItem -Path (Join-Path $artifactsFolder "$project-$refname-$($buildMode)Dependencies-*.*.*.*/*.app")) | ForEach-Object { $_.FullName } )
225+
$dependencies += @((Get-ChildItem -Path (Join-Path $artifactsFolder "$project-$refname-$($buildMode)Dependencies-$artifactVersionFilter/*.app")) | ForEach-Object { $_.FullName } )
210226
}
211227
if (!($projectApps)) {
212228
if ($project -ne '*') {
@@ -338,6 +354,9 @@ else {
338354
elseif (!$sandboxEnvironment -and $deploymentSettings.includeTestAppsInSandboxEnvironment) {
339355
Write-Host "::Warning::Ignoring environment $($deploymentSettings.EnvironmentName), which is a production environment, as test apps can only be deployed to sandbox environments"
340356
}
357+
elseif (!$sandboxEnvironment -and $artifactsVersion -like "PR_*") {
358+
Write-Host "::Warning::Ignoring environment $($deploymentSettings.EnvironmentName), which is a production environment, as deploying from a PR is only supported in sandbox environments"
359+
}
341360
else {
342361
if ($dependencies) {
343362
InstallOrUpgradeApps -bcAuthContext $bcAuthContext -environment $deploymentSettings.EnvironmentName -Apps $dependencies -installMode $deploymentSettings.DependencyInstallMode

Actions/Deploy/Deploy.psm1

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<#
2+
.SYNOPSIS
3+
Get the head ref from a PR
4+
.PARAMETER repository
5+
Repository to search in
6+
.PARAMETER prId
7+
The PR Id
8+
.PARAMETER token
9+
Auth token
10+
#>
11+
function GetHeadRefFromPRId {
12+
Param(
13+
[Parameter(Mandatory = $true)]
14+
[string] $repository,
15+
[Parameter(Mandatory = $true)]
16+
[string] $prId,
17+
[Parameter(Mandatory = $true)]
18+
[string] $token
19+
)
20+
21+
$headers = GetHeaders -token $token
22+
23+
$pullsURI = "https://api.github.com/repos/$repository/pulls/$prId"
24+
Write-Host "- $pullsURI"
25+
$pr = (InvokeWebRequest -Headers $headers -Uri $pullsURI).Content | ConvertFrom-Json
26+
27+
return $pr.head.ref
28+
}

Actions/Deploy/action.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ inputs:
55
description: Shell in which you want to run the action (powershell or pwsh)
66
required: false
77
default: powershell
8+
token:
9+
description: The GitHub token running the action
10+
required: false
11+
default: ${{ github.token }}
812
environmentName:
913
description: Name of environment to deploy to
1014
required: true
@@ -18,6 +22,10 @@ inputs:
1822
deploymentEnvironmentsJson:
1923
description: The settings for all Deployment Environments
2024
required: true
25+
artifactsVersion:
26+
description: Artifacts version. Used to check if this is a deployment from a PR
27+
required: false
28+
default: ''
2129
outputs:
2230
environmentUrl:
2331
description: The URL of the deployed environment
@@ -29,13 +37,15 @@ runs:
2937
shell: ${{ inputs.shell }}
3038
id: Deploy
3139
env:
40+
_token: ${{ inputs.token }}
3241
_environmentName: ${{ inputs.environmentName }}
3342
_artifactsFolder: ${{ inputs.artifactsFolder }}
3443
_type: ${{ inputs.type }}
3544
_deploymentEnvironmentsJson: ${{ inputs.deploymentEnvironmentsJson }}
45+
_artifactsVersion: ${{ inputs.artifactsVersion }}
3646
run: |
3747
${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "Deploy" -Action {
38-
${{ github.action_path }}/Deploy.ps1 -environmentName $ENV:_environmentName -artifactsFolder $ENV:_artifactsFolder -type $ENV:_type -deploymentEnvironmentsJson $ENV:_deploymentEnvironmentsJson
48+
${{ github.action_path }}/Deploy.ps1 -token $ENV:_token -environmentName $ENV:_environmentName -artifactsFolder $ENV:_artifactsFolder -type $ENV:_type -deploymentEnvironmentsJson $ENV:_deploymentEnvironmentsJson -artifactsVersion $ENV:_artifactsVersion
3949
}
4050
branding:
4151
icon: terminal

Actions/GetArtifactsForDeployment/GetArtifactsForDeployment.ps1

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ Param(
77
[string] $artifactsFolder
88
)
99

10+
Import-Module (Join-Path -Path $PSScriptRoot "GetArtifactsForDeployment.psm1")
1011
. (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve)
1112
DownloadAndImportBcContainerHelper
1213

1314
# Get artifacts for all projects
1415
$projects = "*"
15-
$artifactsToDownload = @("Apps", "TestApps", "Dependencies", "PowerPlatformSolution")
16+
$artifactsToDownload = @("Apps","TestApps","Dependencies","PowerPlatformSolution")
1617

1718
Write-Host "Get artifacts for version: '$artifactsVersion' for these projects: '$projects' to folder: '$artifactsFolder'"
1819

@@ -52,6 +53,53 @@ if ($artifactsVersion -eq "current" -or $artifactsVersion -eq "prerelease" -or $
5253
}
5354
}
5455
}
56+
elseif ($artifactsVersion -like "PR_*") {
57+
$prId = $artifactsVersion.Substring(3)
58+
if (!($prId -as [int])) {
59+
throw "Invalid PR id: $prId"
60+
}
61+
$prLatestCommitSha = GetLatestCommitShaFromPRId -repository $ENV:GITHUB_REPOSITORY -prId $prId -token $token
62+
if (!($prLatestCommitSha)) {
63+
throw "Unable to locate commit sha for PR $prId"
64+
}
65+
$latestPRBuildId, $lastKnownGoodBuildId = FindLatestPRRun -repository $ENV:GITHUB_REPOSITORY -commitSha $prLatestCommitSha -token $token
66+
if ($latestPRBuildId -eq 0) {
67+
$prLink = "https://github.com/$($ENV:GITHUB_REPOSITORY)/pull/$prId"
68+
throw "Latest PR build for PR $prId not found, not completed or not successful - Please re-run this workflow when you have a successful build on PR_$prId ($prLink)"
69+
}
70+
71+
$prArtifacts = @()
72+
$expiredArtifacts = @()
73+
$lastKnownGoodBuildArtifacts = @()
74+
# Get PR artifacts
75+
$artifactsToDownload | ForEach-Object {
76+
$prArtifacts += GetArtifactsFromWorkflowRun -workflowRun $latestPRBuildId -token $token -api_url $ENV:GITHUB_API_URL -repository $ENV:GITHUB_REPOSITORY -mask $_ -projects $projects -expiredArtifacts ([ref]$expiredArtifacts)
77+
}
78+
# Get last known good build artifacts referenced from PR
79+
if ($lastKnownGoodBuildId -ne 0) {
80+
Write-Host "Last known good build id: $lastKnownGoodBuildId"
81+
$artifactsToDownload | ForEach-Object {
82+
$lastKnownGoodBuildArtifacts += GetArtifactsFromWorkflowRun -workflowRun $lastKnownGoodBuildId -token $token -api_url $ENV:GITHUB_API_URL -repository $ENV:GITHUB_REPOSITORY -mask $_ -projects $projects -expiredArtifacts ([ref]$expiredArtifacts)
83+
}
84+
}
85+
else {
86+
Write-Host "No last known good build found."
87+
}
88+
89+
if ($expiredArtifacts) {
90+
$prBuildLink = "https://github.com/$($ENV:GITHUB_REPOSITORY)/actions/runs/$latestPRBuildId"
91+
$shortLivedRetentionSettingLink = "https://aka.ms/algosettings#shortLivedArtifactsRetentionDays"
92+
throw "Build artifacts are expired, please re-run the pull request build ($prBuildLink). Note that you can control the retention days of short-lived artifacts using the AL-Go setting ShortLivedArtifactsRetentionDays. See $shortLivedRetentionSettingLink"
93+
}
94+
95+
if ($prArtifacts) {
96+
OutputMessageAndArray -message "Artifacts from pr build" -arrayOfStrings $prArtifacts.Name
97+
}
98+
if ($lastKnownGoodBuildArtifacts) {
99+
OutputMessageAndArray -message "Artifacts from last known good build" -arrayOfStrings $lastKnownGoodBuildArtifacts.Name
100+
}
101+
DownloadPRArtifacts -token $token -path $artifactsFolder -prArtifacts $prArtifacts -lastKnownGoodBuildArtifacts $lastKnownGoodBuildArtifacts -prRunId $latestPRBuildId -lastKnownGoodBuildRunId $lastKnownGoodBuildId
102+
}
55103
else {
56104
$searchArtifacts = $true
57105
}
@@ -61,7 +109,6 @@ if ($searchArtifacts) {
61109
$artifactsToDownload | ForEach-Object {
62110
$allArtifacts += @(GetArtifacts -token $token -api_url $ENV:GITHUB_API_URL -repository $ENV:GITHUB_REPOSITORY -mask $_ -projects $projects -version $artifactsVersion -branch $ENV:GITHUB_REF_NAME)
63111
}
64-
65112
if ($allArtifacts) {
66113
$allArtifacts | ForEach-Object {
67114
$folder = DownloadArtifact -token $token -artifact $_ -path $artifactsFolder -unpack

0 commit comments

Comments
 (0)