From f8c37d686bc0b08b7d4193ce594052f7957af0cc Mon Sep 17 00:00:00 2001 From: spetersenms Date: Fri, 20 Mar 2026 17:02:51 +0100 Subject: [PATCH 1/8] New setting to control no environments fail action --- Actions/.Modules/ReadSettings.psm1 | 1 + Actions/.Modules/settings.schema.json | 5 ++++ .../DetermineDeploymentEnvironments.ps1 | 25 ++++++++++++++++++- Scenarios/settings.md | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Actions/.Modules/ReadSettings.psm1 b/Actions/.Modules/ReadSettings.psm1 index 46a07e4958..b37ea6d26d 100644 --- a/Actions/.Modules/ReadSettings.psm1 +++ b/Actions/.Modules/ReadSettings.psm1 @@ -219,6 +219,7 @@ function GetDefaultSettings } "fullBuildPatterns" = @() "excludeEnvironments" = @() + "noMatchingEnvironmentsAction" = "ignore" "alDoc" = [ordered]@{ "continuousDeployment" = $false "deployToGitHubPages" = $true diff --git a/Actions/.Modules/settings.schema.json b/Actions/.Modules/settings.schema.json index af08720d34..bd5ac2c8fe 100644 --- a/Actions/.Modules/settings.schema.json +++ b/Actions/.Modules/settings.schema.json @@ -554,6 +554,11 @@ }, "description": "An array of environments to be excluded from the build. See https://aka.ms/ALGoSettings#excludeenvironments" }, + "noMatchingEnvironmentsAction": { + "type": "string", + "pattern": "^(ignore|warning|error)$", + "description": "Specifies what happens when deployment environments are found but all are excluded by branch policies or deployment type filters. Allowed values are ignore, warning and error. See https://aka.ms/ALGoSettings#nomatchingenvironmentsaction" + }, "alDoc": { "type": "object", "properties": { diff --git a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 index 6fc16f99ed..eebd33d7ba 100644 --- a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 +++ b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 @@ -270,7 +270,15 @@ else { } } if (!$includeEnvironment) { - Write-Host "Environment $environmentName is not setup for deployments from branch $ENV:GITHUB_REF_NAME" + if ($deploymentSettings.BranchesFromPolicy -and $deploymentSettings.BranchesFromPolicy.Count -gt 0) { + Write-Host "Environment $environmentName is not setup for deployments from branch '$($ENV:GITHUB_REF_NAME)' (GitHub policy allows branches: $($deploymentSettings.BranchesFromPolicy -join ', '))" + } + elseif ($deploymentSettings.Branches -and $deploymentSettings.Branches.Count -gt 0) { + Write-Host "Environment $environmentName is not setup for deployments from branch '$($ENV:GITHUB_REF_NAME)' (allowed branches in settings: $($deploymentSettings.Branches -join ', '))" + } + else { + Write-Host "Environment $environmentName is not setup for deployments from branch '$($ENV:GITHUB_REF_NAME)' (no branch policy defined - only 'main' is allowed by default)" + } } } if ($includeEnvironment) { @@ -304,3 +312,18 @@ Write-Host "EnvironmentCount=$($deploymentEnvironments.Keys.Count)" Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "UnknownEnvironment=$unknownEnvironment" Write-Host "UnknownEnvironment=$unknownEnvironment" + +# Handle noMatchingEnvironmentsAction when environments were found but all filtered out +if ($deploymentEnvironments.Keys.Count -eq 0 -and $environments -and @($environments).Count -gt 0) { + $noMatchAction = if ($settings.ContainsKey('noMatchingEnvironmentsAction')) { $settings.noMatchingEnvironmentsAction } else { 'ignore' } + $message = "No environments matched deployment criteria. $(@($environments).Count) environment(s) were found ($($environments -join ', ')) but all were excluded by branch policies or deployment type filters. Current branch: $ENV:GITHUB_REF_NAME" + switch ($noMatchAction) { + 'warning' { + OutputWarning $message + } + 'error' { + throw $message + } + # 'ignore' - current behavior, do nothing + } +} diff --git a/Scenarios/settings.md b/Scenarios/settings.md index 53573420a8..ef9eab1688 100644 --- a/Scenarios/settings.md +++ b/Scenarios/settings.md @@ -130,6 +130,7 @@ The repository settings are only read from the repository settings file (.github | enableTaskScheduler | Setting enableTaskScheduler to true in your project setting file, causes the build container to be created with the Task Scheduler running. | false | | useCompilerFolder | Setting useCompilerFolder to true causes your pipelines to use containerless compiling. Unless you also set **doNotPublishApps** to true, setting useCompilerFolder to true won't give you any performance advantage, since AL-Go for GitHub will still need to create a container in order to publish and test the apps. In the future, publishing and testing will be split from building and there will be other options for getting an instance of Business Central for publishing and testing. **Note** when using UseCompilerFolder you need to sign apps using the new signing mechanism described [here](../Scenarios/Codesigning.md). | false | | excludeEnvironments | excludeEnvironments can be an array of GitHub Environments, which should be excluded from the list of environments considered for deployment. github-pages is automatically added to this array and cannot be used as environment for deployment of AL-Go for GitHub projects. | [ ] | +| noMatchingEnvironmentsAction | Specifies what happens when deployment environments are found but all are excluded by branch policies or deployment type filters, resulting in nothing being deployed. Allowed values are **ignore** (workflow succeeds silently, current default behavior), **warning** (workflow succeeds but shows a visible warning annotation), and **error** (workflow fails with a clear error message). | ignore | | trustMicrosoftNuGetFeeds | Unless this setting is set to false, AL-Go for GitHub will trust the NuGet feeds provided by Microsoft. The feeds provided by Microsoft contains all Microsoft apps, all Microsoft symbols and symbols for all AppSource apps. | true | | trustedNuGetFeeds | trustedNuGetFeeds can be an array of NuGet feed specifications, which AL-Go for GitHub will use for dependency resolution. Every feed specification must include a URL property and can optionally include a few other properties:
**url** = The URL of the feed (examples: https://pkgs.dev.azure.com/myorg/apps/\_packaging/myrepo/nuget/v3/index.json or https://nuget.pkg.github.com/mygithuborg/index.json").
**authTokenSecret** = If the NuGet feed specified by URL is private, the authTokenSecret must be the name of a secret containing the authentication token with permissions to search and read packages from the NuGet feed.
**patterns** = AL-Go for GitHub will only trust packages, where the ID matches this pattern. Default is all packages (\*).
**fingerprints** = If specified, AL-Go for GitHub will only trust packages signed with a certificate with a fingerprint matching one of the fingerprints in this array. | [ ] | | nuGetFeedSelectMode | Determines the select mode when finding Business Central app packages from NuGet feeds, based on the dependency version specified in app.json. Options are:
- `Earliest` for earliest version of the package
- `EarliestMatching` for earliest version of the package also compatible with the Business Central version used
- `Exact` for the exact version of the package
- `Latest` for the latest version of the package
- `LatestMatching` for the latest version of the package also compatible with the Business Central version used. | LatestMatching | From 3b78d64b8b66fcad0755612d418e28022b566852 Mon Sep 17 00:00:00 2001 From: spetersenms Date: Fri, 20 Mar 2026 17:03:03 +0100 Subject: [PATCH 2/8] Output branch in workflow info --- Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 b/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 index 555b0e4067..7052236d96 100644 --- a/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 +++ b/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 @@ -1,12 +1,13 @@ -Write-Host "Event name: $env:GITHUB_EVENT_NAME" -if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') { - Write-Host "Inputs:" - $eventPath = Get-Content -Encoding UTF8 -Path $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json - if ($null -ne $eventPath.inputs) { - $eventPath.inputs.psObject.Properties | Sort-Object { $_.Name } | ForEach-Object { - $property = $_.Name - $value = $eventPath.inputs."$property" - Write-Host "- $property = '$value'" - } - } -} +Write-Host "Event name: $env:GITHUB_EVENT_NAME" +Write-Host "Branch: $env:GITHUB_REF_NAME" +if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') { + Write-Host "Inputs:" + $eventPath = Get-Content -Encoding UTF8 -Path $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json + if ($null -ne $eventPath.inputs) { + $eventPath.inputs.psObject.Properties | Sort-Object { $_.Name } | ForEach-Object { + $property = $_.Name + $value = $eventPath.inputs."$property" + Write-Host "- $property = '$value'" + } + } +} From 328f555bb99320c228c48e74c94f6259cb6d3cfd Mon Sep 17 00:00:00 2001 From: spetersenms Date: Fri, 20 Mar 2026 17:03:09 +0100 Subject: [PATCH 3/8] test changes --- .../DetermineDeploymentEnvironments.Test.ps1 | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index 6b90ef76ad..7db01dbcea 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -331,4 +331,67 @@ Describe "DetermineDeploymentEnvironments Action Test" { $EnvironmentCount | Should -Be 0 $UnknownEnvironment | Should -Be 0 } + + # noMatchingEnvironmentsAction = ignore (default) - should succeed silently when all environments are filtered out by branch policy + It 'Test calling action directly - noMatchingEnvironmentsAction ignore should succeed silently' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() } ) })} + } + + $settings = @{ + "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ) + "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } + "noMatchingEnvironmentsAction" = "ignore" + "DeployToTest" = @{ "Branches" = @("release/*") } + } + $env:Settings = $settings | ConvertTo-Json -Compress + $env:GITHUB_REF_NAME = "feature/my-feature" + + # Should succeed silently with 0 environments + . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' + PassGeneratedOutput + $EnvironmentCount | Should -Be 0 + } + + # noMatchingEnvironmentsAction = warning - should succeed with a warning when all environments are filtered out by branch policy + It 'Test calling action directly - noMatchingEnvironmentsAction warning should output warning' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() } ) })} + } + + $settings = @{ + "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ) + "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } + "noMatchingEnvironmentsAction" = "warning" + "DeployToTest" = @{ "Branches" = @("release/*") } + } + $env:Settings = $settings | ConvertTo-Json -Compress + $env:GITHUB_REF_NAME = "feature/my-feature" + + # Should succeed but output a warning + . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' 3>&1 -WarningVariable warningOutput | Out-Null + PassGeneratedOutput + $EnvironmentCount | Should -Be 0 + # Verify the warning was emitted (OutputWarning writes to warning stream when running locally) + $warningOutput | Should -Match "No environments matched deployment criteria" + } + + # noMatchingEnvironmentsAction = error - should throw when all environments are filtered out by branch policy + It 'Test calling action directly - noMatchingEnvironmentsAction error should throw' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() } ) })} + } + + $settings = @{ + "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ) + "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } + "noMatchingEnvironmentsAction" = "error" + "DeployToTest" = @{ "Branches" = @("release/*") } + } + $env:Settings = $settings | ConvertTo-Json -Compress + $env:GITHUB_REF_NAME = "feature/my-feature" + + # Should throw with a clear error message + { . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' } | Should -Throw "*No environments matched deployment criteria*" + } } From 17fb902d1ceb931eabe07e65341bdfac557b585f Mon Sep 17 00:00:00 2001 From: spetersenms Date: Fri, 10 Apr 2026 15:05:33 +0200 Subject: [PATCH 4/8] Fix test --- Tests/DetermineDeploymentEnvironments.Test.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index 7db01dbcea..d305268b50 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -369,11 +369,13 @@ Describe "DetermineDeploymentEnvironments Action Test" { $env:GITHUB_REF_NAME = "feature/my-feature" # Should succeed but output a warning - . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' 3>&1 -WarningVariable warningOutput | Out-Null + # OutputWarning uses Write-Warning when running locally, but Write-Host (::Warning::) on GitHub Actions. + # Capture all output streams so we can check for the message in either case. + $allOutput = . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' *>&1 PassGeneratedOutput $EnvironmentCount | Should -Be 0 - # Verify the warning was emitted (OutputWarning writes to warning stream when running locally) - $warningOutput | Should -Match "No environments matched deployment criteria" + # Verify the warning was emitted in any output stream + $allOutput | Should -Match "No environments matched deployment criteria" } # noMatchingEnvironmentsAction = error - should throw when all environments are filtered out by branch policy From 62955f5901abdccf51eaf1e92b4fd271b4ac9458 Mon Sep 17 00:00:00 2001 From: spetersenms Date: Thu, 30 Apr 2026 11:48:50 +0200 Subject: [PATCH 5/8] Fix noMatchingEnvironmentsAction warning test assertion The test piped an array to Should -Match, which in Pester 5 asserts that every element matches the regex. The first non-matching element (e.g. GenerateALDocArtifact=1) caused the assertion to fail even though the warning was correctly emitted. Fix by joining output with Out-String before matching, so the regex checks the combined text for the warning message. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Tests/DetermineDeploymentEnvironments.Test.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index d305268b50..ed46f0e110 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -375,7 +375,8 @@ Describe "DetermineDeploymentEnvironments Action Test" { PassGeneratedOutput $EnvironmentCount | Should -Be 0 # Verify the warning was emitted in any output stream - $allOutput | Should -Match "No environments matched deployment criteria" + # Use Out-String so Should -Match checks the combined text rather than requiring every element to match + ($allOutput | Out-String) | Should -Match "No environments matched deployment criteria" } # noMatchingEnvironmentsAction = error - should throw when all environments are filtered out by branch policy From 8f7fdc96b7536df33ae9673cd454ae9c098fe97f Mon Sep 17 00:00:00 2001 From: spetersenms Date: Mon, 31 Aug 2026 17:19:17 +0200 Subject: [PATCH 6/8] Clean up documentation and add extra test case --- Actions/.Modules/ReadSettings.psm1 | 2 +- .../DetermineDeploymentEnvironments.ps1 | 6 +++-- Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 | 26 +++++++++---------- RELEASENOTES.md | 5 ++++ Scenarios/settings.md | 1 - .../DetermineDeploymentEnvironments.Test.ps1 | 21 +++++++++++++++ 6 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Actions/.Modules/ReadSettings.psm1 b/Actions/.Modules/ReadSettings.psm1 index a692baec99..14d23a7eab 100644 --- a/Actions/.Modules/ReadSettings.psm1 +++ b/Actions/.Modules/ReadSettings.psm1 @@ -226,7 +226,7 @@ function GetDefaultSettings } "fullBuildPatterns" = @() "excludeEnvironments" = @() - "noMatchingEnvironmentsAction" = "ignore" + "noMatchingEnvironmentsAction" = "ignore" "alDoc" = [ordered]@{ "continuousDeployment" = $false "deployToGitHubPages" = $true diff --git a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 index eebd33d7ba..c331f1529e 100644 --- a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 +++ b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 @@ -313,8 +313,10 @@ Write-Host "EnvironmentCount=$($deploymentEnvironments.Keys.Count)" Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "UnknownEnvironment=$unknownEnvironment" Write-Host "UnknownEnvironment=$unknownEnvironment" -# Handle noMatchingEnvironmentsAction when environments were found but all filtered out -if ($deploymentEnvironments.Keys.Count -eq 0 -and $environments -and @($environments).Count -gt 0) { +# Handle noMatchingEnvironmentsAction when environments were found but all filtered out. +# Only applies to manual 'Publish' deployments - for continuous deployment (CD), matching zero +# environments (e.g. when pushing to a branch that no environment allows) is expected and must not fail. +if ($type -eq 'Publish' -and $deploymentEnvironments.Keys.Count -eq 0 -and $environments -and @($environments).Count -gt 0) { $noMatchAction = if ($settings.ContainsKey('noMatchingEnvironmentsAction')) { $settings.noMatchingEnvironmentsAction } else { 'ignore' } $message = "No environments matched deployment criteria. $(@($environments).Count) environment(s) were found ($($environments -join ', ')) but all were excluded by branch policies or deployment type filters. Current branch: $ENV:GITHUB_REF_NAME" switch ($noMatchAction) { diff --git a/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 b/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 index 7052236d96..3fd5294863 100644 --- a/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 +++ b/Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1 @@ -1,13 +1,13 @@ -Write-Host "Event name: $env:GITHUB_EVENT_NAME" -Write-Host "Branch: $env:GITHUB_REF_NAME" -if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') { - Write-Host "Inputs:" - $eventPath = Get-Content -Encoding UTF8 -Path $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json - if ($null -ne $eventPath.inputs) { - $eventPath.inputs.psObject.Properties | Sort-Object { $_.Name } | ForEach-Object { - $property = $_.Name - $value = $eventPath.inputs."$property" - Write-Host "- $property = '$value'" - } - } -} +Write-Host "Event name: $env:GITHUB_EVENT_NAME" +Write-Host "Branch: $env:GITHUB_REF_NAME" +if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') { + Write-Host "Inputs:" + $eventPath = Get-Content -Encoding UTF8 -Path $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json + if ($null -ne $eventPath.inputs) { + $eventPath.inputs.psObject.Properties | Sort-Object { $_.Name } | ForEach-Object { + $property = $_.Name + $value = $eventPath.inputs."$property" + Write-Host "- $property = '$value'" + } + } +} diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ab0eec036a..aadadb15b1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,9 +1,14 @@ +### New setting noMatchingEnvironmentsAction to control behavior when nothing is deployed + +The manual `Publish To Environment` workflow could report success even when no environment matched the deployment criteria (for example when the selected branch is not allowed by the environment branch policy), making it look like a deployment happened when it did not. A new setting `noMatchingEnvironmentsAction` controls this behavior for `Publish` deployments. Allowed values are `ignore` (default, workflow succeeds silently as before), `warning` (workflow succeeds but shows a visible warning annotation) and `error` (workflow fails with a clear error message). Continuous deployment is unaffected, since matching zero environments is expected there. The `DumpWorkflowInfo` action now also logs the branch, and the skip message explains which branches are allowed for the environment. + ### Optimized dependency artifact downloads for multi-project repositories The `DownloadProjectDependencies` action now downloads only artifacts from dependency projects instead of all workflow artifacts. For repositories with many AL-Go projects, this reduces build runner bandwidth and speeds up the dependency download step. ### Issues +- Issue 2147 - Publish To Environment workflow does not log user inputs and reports false success when environments are skipped - Incremental builds (`modifiedApps` mode) now correctly identify unmodified apps for projects whose `appFolders` reference paths outside the project directory (e.g. using `../`) - Issue 2204 - Workspace compilation ignores vsixFile setting - Issue 2211 - Cannot create a release if a project contains only test apps diff --git a/Scenarios/settings.md b/Scenarios/settings.md index 2d2d6124c3..cae0931176 100644 --- a/Scenarios/settings.md +++ b/Scenarios/settings.md @@ -131,7 +131,6 @@ The repository settings are only read from the repository settings file (.github | assignPremiumPlan | Setting assignPremiumPlan to true in your project setting file, causes the build container to be created with the AssignPremiumPlan set. This causes the auto-created user to have Premium Plan enabled. This setting is needed if your tests require premium plan enabled. | false | | enableTaskScheduler | Setting enableTaskScheduler to true in your project setting file, causes the build container to be created with the Task Scheduler running. | false | | useCompilerFolder | Setting useCompilerFolder to true causes your pipelines to use containerless compiling. Unless you also set **doNotPublishApps** to true, setting useCompilerFolder to true won't give you any performance advantage, since AL-Go for GitHub will still need to create a container in order to publish and test the apps. In the future, publishing and testing will be split from building and there will be other options for getting an instance of Business Central for publishing and testing. **Note** when using UseCompilerFolder you need to sign apps using the new signing mechanism described [here](../Scenarios/Codesigning.md). | false | -| excludeEnvironments | excludeEnvironments can be an array of GitHub Environments, which should be excluded from the list of environments considered for deployment. github-pages is automatically added to this array and cannot be used as environment for deployment of AL-Go for GitHub projects. | [ ] | | noMatchingEnvironmentsAction | Specifies what happens when deployment environments are found but all are excluded by branch policies or deployment type filters, resulting in nothing being deployed. Allowed values are **ignore** (workflow succeeds silently, current default behavior), **warning** (workflow succeeds but shows a visible warning annotation), and **error** (workflow fails with a clear error message). | ignore | | workspaceCompilation | **PREVIEW:** Configuration for workspace compilation. This uses the AL tool to compile all apps in the workspace in a single operation, which can improve build performance for repositories with multiple apps. Like **useCompilerFolder**, this is containerless compiling.
**enabled** - Set to true to enable workspace compilation. Default: false.
**parallelism** - The number of parallel compilation processes. Set to 0 or -1 to use all available processors. Default: 1.

**Current limitations:**
  • Upgrade testing is not performed (previousApps are not downloaded).
  • AppSourceCop baseline validation against the previous release is not supported.
  • BCPT test folders are not compiled by workspace compilation.
  • Linux runners are not supported yet.
| { "enabled": false, "parallelism": 1 } | | excludeEnvironments| excludeEnvironments can be an array of GitHub Environments, which should be excluded from the list of environments considered for deployment. github-pages is automatically added to this array and cannot be used as environment for deployment of AL-Go for GitHub projects. | [ ] | diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index ed46f0e110..9761440964 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -397,4 +397,25 @@ Describe "DetermineDeploymentEnvironments Action Test" { # Should throw with a clear error message { . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' } | Should -Throw "*No environments matched deployment criteria*" } + + # noMatchingEnvironmentsAction should NOT affect continuous deployment (CD) - matching zero environments is expected there + It 'Test calling action directly - noMatchingEnvironmentsAction error should not throw for CD' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() } ) })} + } + + $settings = @{ + "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ) + "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } + "noMatchingEnvironmentsAction" = "error" + "DeployToTest" = @{ "Branches" = @("release/*") } + } + $env:Settings = $settings | ConvertTo-Json -Compress + $env:GITHUB_REF_NAME = "feature/my-feature" + + # Should not throw for CD, even with error setting - and should end up with 0 environments + . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'CD' + PassGeneratedOutput + $EnvironmentCount | Should -Be 0 + } } From d30e1cf64ec23b36bc27aa32734edd08ecf5b34f Mon Sep 17 00:00:00 2001 From: spetersenms Date: Tue, 1 Sep 2026 09:06:32 +0200 Subject: [PATCH 7/8] Address PR review: schema enum/default and combined branch-policy message - Use enum + default (ignore) instead of regex pattern for noMatchingEnvironmentsAction in settings schema - Report both GitHub policy and settings Branches allowed lists in skip message when both are configured, so the actual rejection reason is not hidden Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- Actions/.Modules/settings.schema.json | 3 ++- .../DetermineDeploymentEnvironments.ps1 | 10 +++++-- .../DetermineDeploymentEnvironments.Test.ps1 | 27 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Actions/.Modules/settings.schema.json b/Actions/.Modules/settings.schema.json index 418d4248a6..06729496eb 100644 --- a/Actions/.Modules/settings.schema.json +++ b/Actions/.Modules/settings.schema.json @@ -596,7 +596,8 @@ }, "noMatchingEnvironmentsAction": { "type": "string", - "pattern": "^(ignore|warning|error)$", + "enum": ["ignore", "warning", "error"], + "default": "ignore", "description": "Specifies what happens when deployment environments are found but all are excluded by branch policies or deployment type filters. Allowed values are ignore, warning and error. See https://aka.ms/ALGoSettings#nomatchingenvironmentsaction" }, "alDoc": { diff --git a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 index 0688b78291..92b1da4cce 100644 --- a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 +++ b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 @@ -270,10 +270,16 @@ else { } } if (!$includeEnvironment) { - if ($deploymentSettings.BranchesFromPolicy -and $deploymentSettings.BranchesFromPolicy.Count -gt 0) { + $hasPolicyBranches = $deploymentSettings.BranchesFromPolicy -and $deploymentSettings.BranchesFromPolicy.Count -gt 0 + $hasSettingsBranches = $deploymentSettings.Branches -and $deploymentSettings.Branches.Count -gt 0 + if ($hasPolicyBranches -and $hasSettingsBranches) { + # Both restrictions are enforced - a branch must satisfy both, so report both allowed lists + Write-Host "Environment $environmentName is not setup for deployments from branch '$($ENV:GITHUB_REF_NAME)' (GitHub policy allows branches: $($deploymentSettings.BranchesFromPolicy -join ', '); allowed branches in settings: $($deploymentSettings.Branches -join ', '))" + } + elseif ($hasPolicyBranches) { Write-Host "Environment $environmentName is not setup for deployments from branch '$($ENV:GITHUB_REF_NAME)' (GitHub policy allows branches: $($deploymentSettings.BranchesFromPolicy -join ', '))" } - elseif ($deploymentSettings.Branches -and $deploymentSettings.Branches.Count -gt 0) { + elseif ($hasSettingsBranches) { Write-Host "Environment $environmentName is not setup for deployments from branch '$($ENV:GITHUB_REF_NAME)' (allowed branches in settings: $($deploymentSettings.Branches -join ', '))" } else { diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index 9761440964..0983addb38 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -418,4 +418,31 @@ Describe "DetermineDeploymentEnvironments Action Test" { PassGeneratedOutput $EnvironmentCount | Should -Be 0 } + + # Skip message should list both allowed branch lists when a GitHub policy and settings Branches are both configured + It 'Test calling action directly - skip message lists both GitHub policy and settings branches' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @( @{ "type" = "branch_policy"}); "deployment_branch_policy" = @{ "protected_branches" = $false; "custom_branch_policies" = $true } } ) })} + } + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/deployment-branch-policies' } -MockWith { + return @{"Content" = (@{ "branch_policies" = @( @{ "name" = "feature/*" } ) } | ConvertTo-Json -Depth 99 -Compress)} + } + + $settings = @{ + "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ) + "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } + "DeployToTest" = @{ "Branches" = @("release/*") } + } + $env:Settings = $settings | ConvertTo-Json -Compress + # Branch passes the GitHub policy (feature/*) but is rejected by the settings Branches (release/*) + $env:GITHUB_REF_NAME = "feature/my-feature" + + $allOutput = . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' *>&1 + PassGeneratedOutput + $EnvironmentCount | Should -Be 0 + # Both allowed lists must be reported so the actual reason is not hidden + $text = $allOutput | Out-String + $text | Should -Match "GitHub policy allows branches: feature/\*" + $text | Should -Match "allowed branches in settings: release/\*" + } } From b891efdda8c0b1a18bccd6912766bb2f56766ad2 Mon Sep 17 00:00:00 2001 From: spetersenms Date: Tue, 1 Sep 2026 11:07:13 +0200 Subject: [PATCH 8/8] Fix PS5 CI test failure from Out-String word-wrapping The combined branch-message test rendered captured output via Out-String, which word-wraps long lines at the console width. On the windows-latest (PS5) runner the wrap split 'GitHub policy allows branches: feature/*' across a newline, breaking the regex match even though production emits the correct message. Match against raw joined output lines instead. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- Tests/DetermineDeploymentEnvironments.Test.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index 0983addb38..df8b5d22ee 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -440,9 +440,11 @@ Describe "DetermineDeploymentEnvironments Action Test" { $allOutput = . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'Publish' *>&1 PassGeneratedOutput $EnvironmentCount | Should -Be 0 - # Both allowed lists must be reported so the actual reason is not hidden - $text = $allOutput | Out-String - $text | Should -Match "GitHub policy allows branches: feature/\*" - $text | Should -Match "allowed branches in settings: release/\*" + # Both allowed lists must be reported so the actual reason is not hidden. + # Match against the raw output lines rather than Out-String, which word-wraps long + # lines at the console width and can split the searched text across a newline. + $skipMessage = @($allOutput | ForEach-Object { "$_" }) -join "`n" + $skipMessage | Should -Match "GitHub policy allows branches: feature/\*" + $skipMessage | Should -Match "allowed branches in settings: release/\*" } }