Skip to content
Open
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
530663c
Initial plan
Copilot Nov 18, 2025
8a356a1
Extract PowerShell code from E2E.yaml into local actions
Copilot Nov 18, 2025
e97149e
Add README documentation for new E2E actions
Copilot Nov 18, 2025
0d2f404
Move E2E actions from Actions/ to .github/actions/
Copilot Nov 19, 2025
7cbba2e
Remove Invoke-AlGoAction.ps1 wrapper and call scripts directly
Copilot Nov 19, 2025
e6a2b0d
Fix code scanning and pre-commit issues in E2E actions
Copilot Nov 19, 2025
32499d0
Remove invalid shell inputs and fix duplicate contentPath logic
Copilot Nov 19, 2025
e0e69a4
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Nov 25, 2025
da92269
Fix E2E failure: change default shell from 'powershell' to 'pwsh' for…
Copilot Nov 25, 2025
5a00241
Add scenariosFilter parameter support to E2EAnalyze action
Copilot Nov 28, 2025
534f104
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Dec 10, 2025
26a8716
Pass scenariosFilter input to E2EAnalyze action
Copilot Dec 10, 2025
8e25c3c
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Dec 15, 2025
fac0f52
Add PSScriptAnalyzer suppressions for credential parameters in E2E ac…
Copilot Dec 16, 2025
c38cd33
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Dec 16, 2025
faa8bc7
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Dec 18, 2025
d8bd92a
Initialize github variable in e2eTestHelper.psm1 for consistent state…
mazhelez Jan 6, 2026
b9cf0c7
Set default repository in CancelAllWorkflows, WaitAllWorkflows, and T…
mazhelez Jan 6, 2026
1f8ab19
Merge branch 'main' of https://github.com/microsoft/AL-Go into copilo…
mazhelez Jan 6, 2026
d374ea9
Set default repository in CommitAndPush function
mazhelez Jan 6, 2026
e3fc5f3
Fix E2E test failure: quote repository names in gh repo create calls
Copilot Jan 15, 2026
b3b0575
Remove incorrect quotes from GitHub Actions outputs in E2ECalculateTe…
Copilot Jan 16, 2026
1bcce32
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jan 19, 2026
599b797
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Feb 4, 2026
6ab711c
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Feb 5, 2026
bc7cfc5
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Feb 16, 2026
b80cf2b
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Feb 17, 2026
39bccf8
Add PSScriptAnalyzer suppression for adminCenterApiCredentialsSecret …
Copilot Feb 17, 2026
db6caee
Merge main branch and add disabled scenarios support to E2EAnalyze
Copilot Feb 27, 2026
4fec411
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Feb 27, 2026
ba6ff3c
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Mar 3, 2026
c488ae0
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Mar 4, 2026
634bfe9
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Mar 6, 2026
99b6173
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jul 9, 2026
2133831
Fix PSAvoidUsingPlainTextForPassword suppressions on E2E credential p…
Copilot Jul 9, 2026
441d2b0
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jul 10, 2026
6ad9096
Merge branch 'main' into copilot/extract-powershell-code
Copilot Jul 17, 2026
38d5765
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jul 23, 2026
0c74213
Address PR review: E2E action fixes
mazhelez Jul 23, 2026
820a941
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jul 24, 2026
41e9313
Address review feedback and fix pre-commit for E2E actions
mazhelez Jul 24, 2026
2f424f1
Add Pester coverage for E2ECalculateTestParams matrix-to-parameter logic
mazhelez Jul 24, 2026
dd31160
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jul 27, 2026
98bafe0
Add invocation-level GITHUB_OUTPUT tests for E2ECalculateTestParams
mazhelez Jul 27, 2026
1b7383a
Merge branch 'main' into copilot/extract-powershell-code
aholstrup1 Jul 28, 2026
be49735
Merge branch 'main' into copilot/extract-powershell-code
mazhelez Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions .github/actions/E2EAnalyze/E2EAnalyze.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
Param(
[Parameter(HelpMessage = "Maximum parallel jobs", Mandatory = $true)]
[int] $maxParallel,
[Parameter(HelpMessage = "Test upgrades from version", Mandatory = $false)]
[string] $testUpgradesFromVersion = 'v5.0',
[Parameter(HelpMessage = "Filter to run specific scenarios (separated by comma, supports wildcards)", Mandatory = $false)]
[string] $scenariosFilter = '*'
Comment thread
mazhelez marked this conversation as resolved.
)

$ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0

<#
.SYNOPSIS
Filters the available E2E scenarios based on a comma-separated wildcard filter and a list of disabled scenarios.
.DESCRIPTION
Returns the scenarios that match at least one of the (comma separated, wildcard enabled) filter patterns and
that are not listed as disabled. The function is pure (no side effects other than host logging) so it can be
unit tested in isolation.
.PARAMETER allScenarios
The full list of available scenario names.
.PARAMETER scenariosFilter
Comma separated list of wildcard patterns. A scenario is included if it matches at least one pattern. Default is '*' (all).
.PARAMETER disabledScenariosConfig
Array of objects (as read from disabled-scenarios.json) each having a 'scenario' and an optional 'reason' property.
.EXAMPLE
Get-E2EScenariosToRun -allScenarios @('a','b','c') -scenariosFilter 'a*,b*'
#>
function Get-E2EScenariosToRun {
Param(
[Parameter(Mandatory = $true)]
[AllowEmptyCollection()]
[string[]] $allScenarios,
[Parameter(Mandatory = $false)]
[string] $scenariosFilter = '*',
[Parameter(Mandatory = $false)]
[AllowEmptyCollection()]
[array] $disabledScenariosConfig = @()
)

$scenariosFilterArr = @($scenariosFilter -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' })
if ($scenariosFilterArr.Count -eq 0) {
$scenariosFilterArr = @('*')
}
# A scenario matches if it is -like at least one of the filter patterns
$filteredScenarios = @($allScenarios | Where-Object { $scenario = $_; @($scenariosFilterArr | Where-Object { $scenario -like $_ }).Count -gt 0 })

# Determine disabled scenarios from config (optional)
$disabledScenarios = @()
if ($disabledScenariosConfig -and @($disabledScenariosConfig).Count -gt 0) {
$disabledScenarios = @($disabledScenariosConfig | ForEach-Object { $_.scenario })
}
Write-Host "Disabled scenarios from config: $($disabledScenarios -join ', ')"

# Filter out disabled scenarios
$scenariosBeforeDisabledFilter = $filteredScenarios
$beforeFilter = $filteredScenarios.Count
$filteredScenarios = @($filteredScenarios | Where-Object { $disabledScenarios -notcontains $_ })
$afterFilter = $filteredScenarios.Count
if ($beforeFilter -ne $afterFilter) {
Write-Host "Filtered out $($beforeFilter - $afterFilter) disabled scenario(s)"
$disabledScenariosConfig | Where-Object { ($scenariosBeforeDisabledFilter -contains $_.scenario) -and ($filteredScenarios -notcontains $_.scenario) } | ForEach-Object {
Write-Host " - $($_.scenario): $($_.reason)"
}
}

return $filteredScenarios
}

if ($MyInvocation.InvocationName -ne '.') {
$modulePath = Join-Path "." "e2eTests/e2eTestHelper.psm1" -resolve
Import-Module $modulePath -DisableNameChecking

$publicTestruns = @{
"max-parallel" = $maxParallel
"fail-fast" = $false
"matrix" = @{
"include" = @()
}
}
$privateTestruns = @{
"max-parallel" = $maxParallel
"fail-fast" = $false
"matrix" = @{
"include" = @()
}
}
@('appSourceApp','PTE') | ForEach-Object {
$type = $_
@('linux','windows') | ForEach-Object {
$os = $_
@('multiProject','singleProject') | ForEach-Object {
$style = $_
$publicTestruns.matrix.include += @{ "type" = $type; "os" = $os; "style" = $style; "Compiler" = "Container" }
$privateTestruns.matrix.include += @{ "type" = $type; "os" = $os; "style" = $style; "Compiler" = "Container" }
if ($type -eq "PTE") {
# Run end 2 end tests using CompilerFolder with Windows+Linux and single/multiproject
$publicTestruns.matrix.include += @{ "type" = $type; "os" = $os; "style" = $style; "Compiler" = "CompilerFolder" }
}
}
}
}
$publicTestrunsJson = $publicTestruns | ConvertTo-Json -depth 99 -compress
$privateTestrunsJson = $privateTestruns | ConvertTo-Json -depth 99 -compress
Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "publictestruns=$publicTestrunsJson"
Write-Host "publictestruns=$publicTestrunsJson"
Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "privatetestruns=$privateTestrunsJson"
Write-Host "privatetestruns=$privateTestrunsJson"

$releaseList = @(gh release list --repo microsoft/AL-Go)
if ($LASTEXITCODE -ne 0) {
throw "Failed to retrieve releases from microsoft/AL-Go. 'gh release list' exited with code $LASTEXITCODE."
}
$releases = @($releaseList | ForEach-Object { $_.split("`t")[0] }) | Where-Object { [Version]($_.trimStart('v')) -ge [Version]($testUpgradesFromVersion.TrimStart('v')) }
$releasesJson = @{
"matrix" = @{
"include" = @($releases | ForEach-Object { @{ "Release" = $_; "type" = 'appSourceApp' }; @{ "Release" = $_; "type" = 'PTE' } } )
};
"max-parallel" = $maxParallel
"fail-fast" = $false
} | ConvertTo-Json -depth 99 -compress
Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "releases=$releasesJson"
Write-Host "releases=$releasesJson"

$allScenarios = @(Get-ChildItem -Path (Join-Path $ENV:GITHUB_WORKSPACE "e2eTests/scenarios/*/runtest.ps1") | ForEach-Object { $_.Directory.Name })

# Load disabled scenarios from config file (optional)
$disabledScenariosConfigPath = Join-Path $ENV:GITHUB_WORKSPACE "e2eTests/disabled-scenarios.json"
$disabledScenariosConfig = @()
if (Test-Path -Path $disabledScenariosConfigPath) {
$disabledScenariosContent = Get-Content -Path $disabledScenariosConfigPath -Encoding UTF8 -Raw
if (-not [string]::IsNullOrWhiteSpace($disabledScenariosContent)) {
$disabledScenariosConfig = @($disabledScenariosContent | ConvertFrom-Json | ConvertTo-HashTable -recurse)
}
}
else {
Write-Host "No disabled-scenarios.json found; proceeding with all scenarios enabled."
}

$filteredScenarios = @(Get-E2EScenariosToRun -allScenarios $allScenarios -scenariosFilter $scenariosFilter -disabledScenariosConfig $disabledScenariosConfig)
Write-Host "Scenarios to run: $($filteredScenarios -join ', ')"

$scenariosJson = @{
"matrix" = @{
"include" = @($filteredScenarios | ForEach-Object { @{ "Scenario" = $_ } })
};
"max-parallel" = $maxParallel
"fail-fast" = $false
} | ConvertTo-Json -depth 99 -compress
Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "scenarios=$scenariosJson"
Write-Host "scenarios=$scenariosJson"
}
17 changes: 17 additions & 0 deletions .github/actions/E2EAnalyze/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# E2E Analyze

Analyzes and generates test matrices for E2E testing including public/private test runs, releases, and scenarios.

## Inputs

- `maxParallel`: Maximum parallel jobs
- `testUpgradesFromVersion`: Test upgrades from version (default: 'v5.0')
- `scenariosFilter`: Filter to run specific scenarios, separated by comma, supports wildcards (default: '\*')
- `token`: GitHub token with permissions to read releases
Comment thread
mazhelez marked this conversation as resolved.

## Outputs

- `publictestruns`: Public test runs matrix
- `privatetestruns`: Private test runs matrix
- `releases`: Releases matrix
- `scenarios`: Scenarios matrix
50 changes: 50 additions & 0 deletions .github/actions/E2EAnalyze/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: E2E Analyze
author: Microsoft Corporation
inputs:
shell:
description: Shell in which you want to run the action (powershell or pwsh)
required: false
default: pwsh
maxParallel:
description: Maximum parallel jobs
required: true
testUpgradesFromVersion:
description: Test upgrades from version
required: false
default: 'v5.0'
scenariosFilter:
description: Filter to run specific scenarios (separated by comma, supports wildcards)
required: false
default: '*'
token:
description: GitHub token with permissions to read releases
required: true
outputs:
publictestruns:
description: Public test runs matrix
value: ${{ steps.run.outputs.publictestruns }}
privatetestruns:
description: Private test runs matrix
value: ${{ steps.run.outputs.privatetestruns }}
releases:
description: Releases matrix
value: ${{ steps.run.outputs.releases }}
scenarios:
description: Scenarios matrix
value: ${{ steps.run.outputs.scenarios }}
runs:
using: composite
steps:
- name: run
id: run
shell: ${{ inputs.shell }}
env:
_maxParallel: ${{ inputs.maxParallel }}
_testUpgradesFromVersion: ${{ inputs.testUpgradesFromVersion }}
_scenariosFilter: ${{ inputs.scenariosFilter }}
GH_TOKEN: ${{ inputs.token }}
run: |
${{ github.action_path }}/E2EAnalyze.ps1 -maxParallel ([int]$ENV:_maxParallel) -testUpgradesFromVersion $ENV:_testUpgradesFromVersion -scenariosFilter $ENV:_scenariosFilter
branding:
icon: activity
color: blue
12 changes: 12 additions & 0 deletions .github/actions/E2ECalculateRepoName/E2ECalculateRepoName.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Param(
[Parameter(HelpMessage = "GitHub owner for test repositories", Mandatory = $false)]
[string] $githubOwner = ''
)

$ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0
$reponame = [System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetTempFileName())
Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "repoName=$repoName"
Write-Host "repoName=$repoName"
if ($githubOwner) {
Write-Host "Repo URL: https://github.com/$githubOwner/$repoName"
}
11 changes: 11 additions & 0 deletions .github/actions/E2ECalculateRepoName/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# E2E Calculate Repo Name

Generates a random repository name for E2E testing.

## Inputs

- `githubOwner`: GitHub owner for test repositories (optional, for logging purposes)

## Outputs

- `repoName`: Generated repository name
28 changes: 28 additions & 0 deletions .github/actions/E2ECalculateRepoName/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: E2E Calculate Repo Name
author: Microsoft Corporation
inputs:
shell:
description: Shell in which you want to run the action (powershell or pwsh)
required: false
default: pwsh
githubOwner:
description: GitHub owner for test repositories (optional, for logging purposes)
required: false
default: ''
outputs:
repoName:
description: Generated repository name
value: ${{ steps.run.outputs.repoName }}
runs:
using: composite
steps:
- name: run
id: run
shell: ${{ inputs.shell }}
env:
_githubOwner: ${{ inputs.githubOwner }}
run: |
${{ github.action_path }}/E2ECalculateRepoName.ps1 -githubOwner $ENV:_githubOwner
branding:
icon: hash
color: blue
Loading
Loading