diff --git a/Actions/.Modules/ReadSettings.psm1 b/Actions/.Modules/ReadSettings.psm1 index d8ea49ff3..cd8c99745 100644 --- a/Actions/.Modules/ReadSettings.psm1 +++ b/Actions/.Modules/ReadSettings.psm1 @@ -220,6 +220,7 @@ function GetDefaultSettings } "fullBuildPatterns" = @() "excludeEnvironments" = @() + "continuousDeployment" = $null "alDoc" = [ordered]@{ "continuousDeployment" = $false "deployToGitHubPages" = $true diff --git a/Actions/.Modules/settings.schema.json b/Actions/.Modules/settings.schema.json index 419fdac01..ffd60c4de 100644 --- a/Actions/.Modules/settings.schema.json +++ b/Actions/.Modules/settings.schema.json @@ -561,6 +561,10 @@ }, "description": "An array of environments to be excluded from the build. See https://aka.ms/ALGoSettings#excludeenvironments" }, + "continuousDeployment": { + "type": "boolean", + "description": "Global default for continuous deployment. When set to false, disables automatic CD for all environments (overrides the name-based default, but not per-environment DeployTo.ContinuousDeployment). Omit to fall back to per-environment name conventions. See https://aka.ms/ALGoSettings#continuousdeployment" + }, "alDoc": { "type": "object", "properties": { diff --git a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 index 6fc16f99e..462ae7f18 100644 --- a/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 +++ b/Actions/DetermineDeploymentEnvironments/DetermineDeploymentEnvironments.ps1 @@ -218,6 +218,11 @@ else { $ghEnvironment = $ghEnvironments | Where-Object { $_.name -eq $environmentName } $deploymentSettings.BranchesFromPolicy = @(Get-BranchesFromPolicy -ghEnvironment $ghEnvironment) + # If continuousDeployment is not set per-environment, check for a global continuousDeployment setting + if ($null -eq $deploymentSettings.continuousDeployment -and $null -ne $settings.continuousDeployment) { + $deploymentSettings.continuousDeployment = $settings.continuousDeployment + } + # Include Environment if: # - Type is not Continous Deployment # - Environment is setup for Continuous Deployment (in settings) diff --git a/Scenarios/settings.md b/Scenarios/settings.md index c11a181aa..a2982972a 100644 --- a/Scenarios/settings.md +++ b/Scenarios/settings.md @@ -131,6 +131,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. | [ ] | +| continuousDeployment | Global default for continuous deployment. When set, this overrides the per-environment default (which is based on environment name conventions), but is itself overridden by any per-environment **DeployTo\** setting with **ContinuousDeployment** specified. Set to **false** to disable automatic CD for all environments globally — for example in an organization settings variable — while still allowing manual deployment via the **Publish To Environment** workflow. Per-environment settings can then opt back in by setting **DeployTo\** with **ContinuousDeployment** = true. | (not set — falls back to per-environment name convention) | | 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 | diff --git a/Tests/DetermineDeploymentEnvironments.Test.ps1 b/Tests/DetermineDeploymentEnvironments.Test.ps1 index 6b90ef76a..5fc6ac52e 100644 --- a/Tests/DetermineDeploymentEnvironments.Test.ps1 +++ b/Tests/DetermineDeploymentEnvironments.Test.ps1 @@ -331,4 +331,70 @@ Describe "DetermineDeploymentEnvironments Action Test" { $EnvironmentCount | Should -Be 0 $UnknownEnvironment | Should -Be 0 } + + # Global continuousDeployment: false disables CD for all environments + It 'Test calling action directly - Global continuousDeployment=false disables CD for all environments' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() }, @{ "name" = "another"; "protection_rules" = @() } ) })} + } + + # Global continuousDeployment=false - no environments should be included in CD + $settings = @{ "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ); "continuousDeployment" = $false; "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } } + $env:Settings = $settings | ConvertTo-Json -Compress + . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'CD' + PassGeneratedOutput + $EnvironmentCount | Should -Be 0 + } + + # Global continuousDeployment: false does not affect Publish + It 'Test calling action directly - Global continuousDeployment=false does not affect Publish' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() }, @{ "name" = "another"; "protection_rules" = @() } ) })} + } + + # Global continuousDeployment=false - Publish should still include all environments + $settings = @{ "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ); "continuousDeployment" = $false; "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } } + $env:Settings = $settings | ConvertTo-Json -Compress + . (Join-Path $scriptRoot $scriptName) -getEnvironments 'test' -type 'Publish' + PassGeneratedOutput + $EnvironmentCount | Should -Be 1 + ($EnvironmentsMatrixJson | ConvertFrom-Json | ConvertTo-HashTable -recurse).matrix.include.environment | Should -Contain "test" + } + + # Per-environment setting overrides global continuousDeployment + It 'Test calling action directly - Per-environment continuousDeployment overrides global setting' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test"; "protection_rules" = @() }, @{ "name" = "another"; "protection_rules" = @() } ) })} + } + + # Global=false but test environment opts back in with per-env setting + $settings = @{ + "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ) + "continuousDeployment" = $false + "DeployToTest" = @{ "continuousDeployment" = $true } + "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } + } + $env:Settings = $settings | ConvertTo-Json -Compress -Depth 5 + . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'CD' + PassGeneratedOutput + $EnvironmentCount | Should -Be 1 + ($EnvironmentsMatrixJson | ConvertFrom-Json | ConvertTo-HashTable -recurse).matrix.include.environment | Should -Contain "test" + ($EnvironmentsMatrixJson | ConvertFrom-Json | ConvertTo-HashTable -recurse).matrix.include.environment | Should -Not -Contain "another" + } + + # No global setting - existing name-based default behaviour is preserved + It 'Test calling action directly - No global continuousDeployment preserves existing name-based default' { + Mock InvokeWebRequest -ParameterFilter { $uri -like '*/environments' } -MockWith { + return @{"Content" = (ConvertTo-Json -Compress -Depth 99 -InputObject @{ "environments" = @( @{ "name" = "test (PROD)"; "protection_rules" = @() }, @{ "name" = "another"; "protection_rules" = @() } ) })} + } + + # No global continuousDeployment - PROD-tagged environment excluded, non-PROD included (existing behaviour) + $settings = @{ "type" = "PTE"; "runs-on" = "ubuntu-latest"; "shell" = "pwsh"; "environments" = @(); "excludeEnvironments" = @( 'github-pages' ); "alDoc" = @{ "continuousDeployment" = $false; "deployToGitHubPages" = $false } } + $env:Settings = $settings | ConvertTo-Json -Compress + . (Join-Path $scriptRoot $scriptName) -getEnvironments '*' -type 'CD' + PassGeneratedOutput + $EnvironmentCount | Should -Be 1 + ($EnvironmentsMatrixJson | ConvertFrom-Json | ConvertTo-HashTable -recurse).matrix.include.environment | Should -Contain "another" + ($EnvironmentsMatrixJson | ConvertFrom-Json | ConvertTo-HashTable -recurse).matrix.include.environment | Should -Not -Contain "test (PROD)" + } }