From 80bb6eebbbe237260b0fd501707a2aeaf38d2128 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 06:50:06 +0000 Subject: [PATCH 1/6] Initial plan From 9baaa45d7eea22dd3077123c97bfd05f8be6a7e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 06:51:42 +0000 Subject: [PATCH 2/6] Fix: allow release when project contains only test apps (issue #2211) Agent-Logs-Url: https://github.com/microsoft/AL-Go/sessions/113d51d9-e145-4f4d-a43f-630553dfd8a8 Co-authored-by: mazhelez <43066499+mazhelez@users.noreply.github.com> --- .../DetermineArtifactsForRelease.ps1 | 6 +++--- RELEASENOTES.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 index 2acf558b15..d58720801b 100644 --- a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 +++ b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 @@ -53,11 +53,11 @@ $projects | ForEach-Object { $buildVersion = "$buildVersion" if ($buildVersion -eq "latest") { Write-Host "Grab latest" - $artifact = $allArtifacts | Where-Object { $_.name -like "$project-$refname-Apps-*.*.*.*" -or $_.name -like "$project-$refname-PowerPlatformSolution-*.*.*.*" } | Select-Object -First 1 + $artifact = $allArtifacts | Where-Object { $_.name -like "$project-$refname-Apps-*.*.*.*" -or $_.name -like "$project-$refname-TestApps-*.*.*.*" -or $_.name -like "$project-$refname-PowerPlatformSolution-*.*.*.*" } | Select-Object -First 1 } else { - Write-Host "Search for $project-$refname-Apps-$buildVersion or $project-$refname-PowerPlatformSolution-$buildVersion" - $artifact = $allArtifacts | Where-Object { $_.name -eq "$project-$refname-Apps-$buildVersion"-or $_.name -eq "$project-$refname-PowerPlatformSolution-$buildVersion" } | Select-Object -First 1 + Write-Host "Search for $project-$refname-Apps-$buildVersion or $project-$refname-TestApps-$buildVersion or $project-$refname-PowerPlatformSolution-$buildVersion" + $artifact = $allArtifacts | Where-Object { $_.name -eq "$project-$refname-Apps-$buildVersion" -or $_.name -eq "$project-$refname-TestApps-$buildVersion" -or $_.name -eq "$project-$refname-PowerPlatformSolution-$buildVersion" } | Select-Object -First 1 } if ($artifact) { $startIndex = $artifact.name.LastIndexOf('-') + 1 diff --git a/RELEASENOTES.md b/RELEASENOTES.md index adfc952a6c..f2e7b622c3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,6 +1,7 @@ ### Issues - Issue 2204 - Workspace compilation ignores vsixFile setting +- Issue 2211 - Cannot create a release if a project contains only test apps ## v9.0 From 89e6159b23d6a4115eeba66c3406ed23214b1f02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:31:47 +0000 Subject: [PATCH 3/6] Skip test-only projects instead of including test artifacts in release Agent-Logs-Url: https://github.com/microsoft/AL-Go/sessions/414c08ff-4c95-4a7a-8b8f-391414752ac6 Co-authored-by: mazhelez <43066499+mazhelez@users.noreply.github.com> --- .../DetermineArtifactsForRelease.ps1 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 index d58720801b..f4e081da8e 100644 --- a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 +++ b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 @@ -53,17 +53,24 @@ $projects | ForEach-Object { $buildVersion = "$buildVersion" if ($buildVersion -eq "latest") { Write-Host "Grab latest" - $artifact = $allArtifacts | Where-Object { $_.name -like "$project-$refname-Apps-*.*.*.*" -or $_.name -like "$project-$refname-TestApps-*.*.*.*" -or $_.name -like "$project-$refname-PowerPlatformSolution-*.*.*.*" } | Select-Object -First 1 + $artifact = $allArtifacts | Where-Object { $_.name -like "$project-$refname-Apps-*.*.*.*" -or $_.name -like "$project-$refname-PowerPlatformSolution-*.*.*.*" } | Select-Object -First 1 } else { - Write-Host "Search for $project-$refname-Apps-$buildVersion or $project-$refname-TestApps-$buildVersion or $project-$refname-PowerPlatformSolution-$buildVersion" - $artifact = $allArtifacts | Where-Object { $_.name -eq "$project-$refname-Apps-$buildVersion" -or $_.name -eq "$project-$refname-TestApps-$buildVersion" -or $_.name -eq "$project-$refname-PowerPlatformSolution-$buildVersion" } | Select-Object -First 1 + Write-Host "Search for $project-$refname-Apps-$buildVersion or $project-$refname-PowerPlatformSolution-$buildVersion" + $artifact = $allArtifacts | Where-Object { $_.name -eq "$project-$refname-Apps-$buildVersion" -or $_.name -eq "$project-$refname-PowerPlatformSolution-$buildVersion" } | Select-Object -First 1 } if ($artifact) { $startIndex = $artifact.name.LastIndexOf('-') + 1 $artifactsVersion = $artifact.name.SubString($startIndex) } else { + # No release artifacts (Apps or PowerPlatformSolution) were found for this project. + # This can happen when a project contains only test apps - in that case, skip the project + # rather than failing the release, as test apps are not part of the release. + if ($allArtifacts | Where-Object { $_.name -like "$project-$refname-TestApps-*.*.*.*" }) { + Write-Host "::Warning::No release artifacts found for project $project, only test artifacts are available. Skipping project for release." + return + } throw "No artifacts found for this project" } if ($sha) { From bda4870e7d3397090d7889ddc8c8cb932a4a86ea Mon Sep 17 00:00:00 2001 From: Maria Zhelezova <43066499+mazhelez@users.noreply.github.com> Date: Mon, 20 Apr 2026 23:06:57 +0200 Subject: [PATCH 4/6] Update Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../DetermineArtifactsForRelease.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 index f4e081da8e..4809eba031 100644 --- a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 +++ b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 @@ -67,7 +67,7 @@ $projects | ForEach-Object { # No release artifacts (Apps or PowerPlatformSolution) were found for this project. # This can happen when a project contains only test apps - in that case, skip the project # rather than failing the release, as test apps are not part of the release. - if ($allArtifacts | Where-Object { $_.name -like "$project-$refname-TestApps-*.*.*.*" }) { + if ($allArtifacts | Where-Object { $_.name -like "$project-$refname-*TestApps-*.*.*.*" }) { Write-Host "::Warning::No release artifacts found for project $project, only test artifacts are available. Skipping project for release." return } From 7fdc6abbfabe2acbbf23176cf664db07daa2d943 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:07:54 +0000 Subject: [PATCH 5/6] Throw clear error when no release artifacts selected for any project Agent-Logs-Url: https://github.com/microsoft/AL-Go/sessions/e1f0a039-a64d-4325-8735-c5761e8c3adf Co-authored-by: mazhelez <43066499+mazhelez@users.noreply.github.com> --- .../DetermineArtifactsForRelease.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 index 4809eba031..3dc5539da1 100644 --- a/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 +++ b/Actions/DetermineArtifactsForRelease/DetermineArtifactsForRelease.ps1 @@ -91,6 +91,9 @@ $projects | ForEach-Object { throw "No artifacts found for version $artifactsVersion" } } +if ($include.Count -eq 0 -or -not $sha) { + throw "No release artifacts found for any project. Ensure that at least one project produces release artifacts (Apps or PowerPlatformSolution) before creating a release." +} $artifacts = @{ "include" = $include } $artifactsJson = $artifacts | ConvertTo-Json -compress Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "artifacts=$artifactsJson" From ef6e97439f99849fa915a66f98a354d438ba9610 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:12:52 +0000 Subject: [PATCH 6/6] Add Pester tests for DetermineArtifactsForRelease artifact selection Agent-Logs-Url: https://github.com/microsoft/AL-Go/sessions/9361538b-0adf-4477-be91-ede701462354 Co-authored-by: mazhelez <43066499+mazhelez@users.noreply.github.com> --- Tests/DetermineArtifactsForRelease.Test.ps1 | 109 +++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/Tests/DetermineArtifactsForRelease.Test.ps1 b/Tests/DetermineArtifactsForRelease.Test.ps1 index 1afea5bad7..e052d145af 100644 --- a/Tests/DetermineArtifactsForRelease.Test.ps1 +++ b/Tests/DetermineArtifactsForRelease.Test.ps1 @@ -1,4 +1,7 @@ -Get-Module Github-Helper | Remove-Module -Force +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Mock/callback parameters must match function signatures')] +param() + +Get-Module Github-Helper | Remove-Module -Force Import-Module (Join-Path $PSScriptRoot '..\Actions\Github-Helper.psm1' -Resolve) Get-Module TestActionsHelper | Remove-Module -Force Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') @@ -15,6 +18,16 @@ Describe 'DetermineArtifactsForRelease Tests' { $scriptPath = Join-Path $scriptRoot $scriptName [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName + + function MockArtifact { + param([string] $name, [string] $sha = 'abc123') + [PSCustomObject]@{ + name = $name + expired = $false + archive_download_url = "https://example.com/artifacts/$name" + workflow_run = [PSCustomObject]@{ head_sha = $sha } + } + } } It 'Compile Action' { @@ -28,4 +41,98 @@ Describe 'DetermineArtifactsForRelease Tests' { } YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs } + + Context 'Artifact selection behavior' { + BeforeAll { + $env:GITHUB_REPOSITORY = 'org/repo' + $env:GITHUB_API_URL = 'https://api.github.com' + $env:GITHUB_REF_NAME = 'main' + $env:Settings = '{"repoName":"repo","type":"PTE","powerPlatformSolutionFolder":""}' + } + + BeforeEach { + $script:githubOutputFile = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) + New-Item -Path $script:githubOutputFile -ItemType File | Out-Null + $env:GITHUB_OUTPUT = $script:githubOutputFile + } + + AfterEach { + if ($script:githubOutputFile -and (Test-Path $script:githubOutputFile)) { + Remove-Item -Path $script:githubOutputFile -Force + } + } + + It 'Mixed projects (apps + test artifacts) produce a non-empty include list' { + $artifacts = @( + (MockArtifact 'proj1-main-Apps-1.0.0.0'), + (MockArtifact 'proj1-main-TestApps-1.0.0.0'), + (MockArtifact 'proj2-main-Apps-1.0.0.0') + ) + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*page=1*' } -MockWith { + [PSCustomObject]@{ total_count = $artifacts.Count; Artifacts = $artifacts } + } + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*page=2*' } -MockWith { + [PSCustomObject]@{ total_count = 0; Artifacts = @() } + } + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*/branches/*' } -MockWith { + [PSCustomObject]@{ commit = [PSCustomObject]@{ sha = 'abc123' } } + } + + & $scriptPath -buildVersion 'latest' -GITHUB_TOKEN 'tok' -TOKENFORPUSH 'tok' -ProjectsJson '["proj1","proj2"]' + + $output = Get-Content $env:GITHUB_OUTPUT -Raw + $output | Should -Match 'commitish=abc123' + $output | Should -Match 'proj1-main-Apps-1\.0\.0\.0' + $output | Should -Match 'proj1-main-TestApps-1\.0\.0\.0' + $output | Should -Match 'proj2-main-Apps-1\.0\.0\.0' + } + + It 'Test-only project is skipped with a warning (including build-mode test artifacts)' { + $artifacts = @( + (MockArtifact 'proj1-main-Apps-1.0.0.0'), + (MockArtifact 'proj2-main-CleanTestApps-1.0.0.0') + ) + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*page=1*' } -MockWith { + [PSCustomObject]@{ total_count = $artifacts.Count; Artifacts = $artifacts } + } + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*page=2*' } -MockWith { + [PSCustomObject]@{ total_count = 0; Artifacts = @() } + } + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*/branches/*' } -MockWith { + [PSCustomObject]@{ commit = [PSCustomObject]@{ sha = 'abc123' } } + } + Mock Write-Host { } -ParameterFilter { "$Object" -like '::Warning::*proj2*' } + + & $scriptPath -buildVersion 'latest' -GITHUB_TOKEN 'tok' -TOKENFORPUSH 'tok' -ProjectsJson '["proj1","proj2"]' + + Assert-MockCalled Write-Host -ParameterFilter { "$Object" -like '::Warning::*proj2*' } -Scope It + $output = Get-Content $env:GITHUB_OUTPUT -Raw + $output | Should -Match 'proj1-main-Apps-1\.0\.0\.0' + $output | Should -Not -Match 'proj2-main-CleanTestApps' + } + + It 'Throws a clear error when no project has releasable artifacts' { + $artifacts = @( + (MockArtifact 'proj1-main-TestApps-1.0.0.0') + ) + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*page=1*' } -MockWith { + [PSCustomObject]@{ total_count = $artifacts.Count; Artifacts = $artifacts } + } + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*page=2*' } -MockWith { + [PSCustomObject]@{ total_count = 0; Artifacts = @() } + } + + { & $scriptPath -buildVersion 'latest' -GITHUB_TOKEN 'tok' -TOKENFORPUSH 'tok' -ProjectsJson '["proj1"]' } | + Should -Throw -ExpectedMessage '*No release artifacts found for any project*' + } + + It 'Throws original error when a project has no artifacts of any kind' { + Mock Invoke-RestMethod -ParameterFilter { $Uri -like '*actions/artifacts*' } -MockWith { + [PSCustomObject]@{ total_count = 0; Artifacts = @() } + } + + { & $scriptPath -buildVersion 'latest' -GITHUB_TOKEN 'tok' -TOKENFORPUSH 'tok' -ProjectsJson '["proj1"]' } | + Should -Throw -ExpectedMessage '*No artifacts found for this project*' + } + } }