diff --git a/.github/actions/TestPreprocessorSymbols/action.ps1 b/.github/actions/TestPreprocessorSymbols/action.ps1 new file mode 100644 index 0000000000..97f45fbddf --- /dev/null +++ b/.github/actions/TestPreprocessorSymbols/action.ps1 @@ -0,0 +1,47 @@ +# Current path is .github/actions/VerifyAppChanges + +Import-Module "$PSScriptRoot\..\..\..\build\scripts\EnlistmentHelperFunctions.psm1" -DisableNameChecking +Import-Module "$PSScriptRoot\..\..\..\build\scripts\GuardingV2ExtensionsHelper.psm1" -DisableNameChecking +Import-Module "$PSScriptRoot\..\..\..\build\scripts\TestPreprocessorSymbols.psm1" -Force + +# Get the major build version from the main branch +$mainVersion = Get-MaxAllowedObsoleteVersion + +# Get the major build version from the current branch +$currentVersion = (Get-ConfigValue -Key "repoVersion" -ConfigType AL-Go) -split '\.' | Select-Object -First 1 + +# CLEANSCHEMA is on a 5y cycle starting from 26 +if ($CurrentVersion -le 26) { + $schemaLowerBound = 15 +} else { + $schemaLowerBound = ([math]::Floor(($CurrentVersion - 2) / 5) * 5) - 2 # makes a series: 23, 28, 33, 38, 43 etc. This is the version is which we clean up (26, 31, 36, etc.) - 3. +} + +# Define the preprocessor symbols to check for +$symbolConfigs = @( + @{stem = "CLEAN"; lowerBound = ($CurrentVersion - 4); upperBound = $mainVersion}, + @{stem = "CLEANSCHEMA"; lowerBound = $schemaLowerBound; upperBound = $mainVersion + 3} # next lowerbound, after cleanup should be 25, then +) + +Write-Host "Checking preprocessor symbols with $symbolConfigs" + +#initialize arrays to store any invalid preprocessor symbols with line numbers +$invalidLowercaseSymbols = @() +$invalidPatternSymbols = @() +$invalidStemSymbols = @() + +$alfiles = (Get-ChildItem -Filter '*.al' -Recurse) | Select-Object -ExpandProperty FullName +foreach ($file in $alfiles) { + # Call the Test-PreprocessorSymbols function with the file path and calculated version bounds + $result = Test-PreprocessorSymbols -filePath $file -symbolConfigs $symbolConfigs + if ($null -ne $result) { + $invalidLowercaseSymbols += $result.invalidLowercaseSymbols + $invalidPatternSymbols += $result.invalidPatternSymbols + $invalidStemSymbols += $result.invalidStemSymbols + } +} + +$symbolErrors = $invalidLowercaseSymbols + $invalidPatternSymbols + $invalidStemSymbols +if ($symbolErrors.Count -gt 0) { + throw "Errors found in preprocessor symbols:`n $symbolErrors" +} \ No newline at end of file diff --git a/.github/actions/TestPreprocessorSymbols/action.yaml b/.github/actions/TestPreprocessorSymbols/action.yaml new file mode 100644 index 0000000000..6a4901c90a --- /dev/null +++ b/.github/actions/TestPreprocessorSymbols/action.yaml @@ -0,0 +1,13 @@ +name: Test Preprocessor Symbols +author: Microsoft Corporation +description: Verifies the preprocessor symbols on .al files +runs: + using: composite + steps: + - name: Test Preprocessor Symbols + shell: pwsh + run: | + ${{ github.action_path }}/action.ps1 +branding: + icon: terminal + color: blue diff --git a/.github/workflows/powershell.yaml b/.github/workflows/PowerShell.yaml similarity index 70% rename from .github/workflows/powershell.yaml rename to .github/workflows/PowerShell.yaml index 16cfd28f50..ac4d712d48 100644 --- a/.github/workflows/powershell.yaml +++ b/.github/workflows/PowerShell.yaml @@ -1,8 +1,4 @@ -# https://github.com/microsoft/action-psscriptanalyzer -# For more information on PSScriptAnalyzer in general, see -# https://github.com/PowerShell/PSScriptAnalyzer - -name: PSScriptAnalyzer +name: 'PowerShell' on: push: @@ -16,8 +12,11 @@ permissions: contents: read jobs: - build: - name: PSScriptAnalyzer + PSScriptAnalyzer: + # https://github.com/microsoft/psscriptanalyzer-action + # For more information on PSScriptAnalyzer in general, see + # https://github.com/PowerShell/PSScriptAnalyzer + name: Run PSScriptAnalyzer runs-on: ubuntu-latest permissions: security-events: write # for github/codeql-action/upload-sarif to upload SARIF results @@ -37,3 +36,13 @@ jobs: uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 with: sarif_file: results.sarif + + RunTests: + name: Run PS Tests + runs-on: windows-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Run PS Tests + run: | + . (Join-Path "." "build/scripts/tests/runTests.ps1") diff --git a/.github/workflows/VerifyAppChanges.yaml b/.github/workflows/VerifyAppChanges.yaml new file mode 100644 index 0000000000..9b606d3006 --- /dev/null +++ b/.github/workflows/VerifyAppChanges.yaml @@ -0,0 +1,21 @@ +name: 'Verify App Changes' + +on: + pull_request: + branches: [ 'main', 'releases/*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + VerifyAppChanges: + runs-on: windows-latest + name: Verify App Changes + steps: + - name: checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + ref: ${{ github.sha }} + + - uses: microsoft/BCApps/.github/actions/TestPreprocessorSymbols@cedb78a7972da09fcdaf9ccaa86aef0ded2b5da7 diff --git a/build/scripts/GuardingV2ExtensionsHelper.psm1 b/build/scripts/GuardingV2ExtensionsHelper.psm1 index 69c55ac3e8..fc3b233cfd 100644 --- a/build/scripts/GuardingV2ExtensionsHelper.psm1 +++ b/build/scripts/GuardingV2ExtensionsHelper.psm1 @@ -205,7 +205,7 @@ function Update-AppSourceCopVersion # All major versions greater than current but less or equal to main should be allowed $currentBuildVersion = [int] $buildVersion.Split('.')[0] - $maxAllowedObsoleteVersion = [int] (GetMaxAllowedObsoleteVersion) + $maxAllowedObsoleteVersion = [int] (Get-MaxAllowedObsoleteVersion) $obsoleteTagAllowedVersions = @() # Add 3 versions for tasks built with CLEANpreProcessorSymbols @@ -257,7 +257,7 @@ function Test-IsStrictModeEnabled return $false } -function GetMaxAllowedObsoleteVersion() { +function Get-MaxAllowedObsoleteVersion() { git fetch origin main $alGoSettings = $(git show origin/main:.github/AL-Go-Settings.json) | ConvertFrom-Json if (-not $alGoSettings.repoVersion) { diff --git a/build/scripts/TestPreprocessorSymbols.psm1 b/build/scripts/TestPreprocessorSymbols.psm1 new file mode 100644 index 0000000000..c113a0169e --- /dev/null +++ b/build/scripts/TestPreprocessorSymbols.psm1 @@ -0,0 +1,130 @@ +<# +.SYNOPSIS + This script checks the preprocessor symbols in an AL file. + +.DESCRIPTION + This script checks the preprocessor symbols in an AL file for the following: + - Ensures there is no space after the '#' character. + - Ensures preprocessor symbols have uppercase stems. + - Ensures preprocessor symbols are within a specified range. + - Ensures preprocessor symbols are in the correct format. + - Ensures preprocessor symbols are not in lowercase. + +.PARAMETER filePath + The path to the file to be checked. + +.PARAMETER symbolConfigs + An array of objects where each entry has a stem, an upper, and a lower bound. + +.EXAMPLE + $alfiles = Get-ChildItem -Recurse -Filter *.al -Path .\App\ + foreach ($alfile in $alfiles) { + $symbolConfigs = @( + @{stem="CLEAN"; lowerBound=22; upperBound=26}, + @{stem="CLEANSCHEMA"; lowerBound=22; upperBound=26} + ) + Test-PreprocessorSymbols -filePath $alfile.FullName -symbolConfigs $symbolConfigs + } + +.NOTES + Author: Gert Robyns + Date: 2024-09-03 + + Updated by: Gert Robyns + Date: 2024-09-20 +#> +function Test-PreprocessorSymbols { + param ( + [Parameter(Mandatory=$true)] + [string]$filePath, + [Parameter(Mandatory=$true)] + [hashtable[]]$symbolConfigs + ) + + # check if extension is .al, else return $null + if ('.al' -ne [system.io.path]::GetExtension($filePath)) { + return $null + } + + # Define the regex pattern for disallowing a space after # + $noSpaceAfterHashPattern = "^#\s" + $lowercasePattern = "^#(if|elseif|else\b|endif)" + $lowercaseNotPattern = "^#if not " + $symbolPattern = @() + + foreach ($config in $symbolConfigs) { + $stem = $config.stem + $lowerBound = $config.lowerBound + $upperBound = $config.upperBound + + # Generate the regex pattern for the SymbolStem range + $rangePattern = "$($lowerBound..$upperBound -join '|')" + + $upperStem = $stem.ToUpper() + $symbolPattern += "^#if\s${upperStem}($rangePattern)" + $symbolPattern += "^#if\snot\s${upperStem}($rangePattern)" + $symbolPattern += "^#elseif\s${upperStem}($rangePattern)" + } + + # Add #endif to the symbol pattern but not to the strict pattern + $symbolPattern += "#else\b" + $symbolPattern += "#endif" + + # Read the content of the file + $content = Get-Content -Path $filePath + + # Initialize lists to store any invalid preprocessor symbols with line numbers + $invalidLowercaseSymbols = @() + $invalidPatternSymbols = @() + $invalidStemSymbols = @() + + # Iterate through each line in the file content with line numbers + for ($i = 0; $i -lt $content.Count; $i++) { + $line = $content[$i] + $lineNumber = $i + 1 + + # Check for space after # + if ($line -cmatch $noSpaceAfterHashPattern) { + $invalidPatternSymbols += "${filePath}:${lineNumber}: $line" + } + + # Check for lowercase + if (($line -match $lowercasePattern) -and ($line -cnotmatch $lowercasePattern)) { + $invalidLowercaseSymbols += "${filePath}:${lineNumber}: $line" + } + + # Check for lowercase not + if (($line -match $lowercaseNotPattern) -and ($line -cnotmatch $lowercaseNotPattern)) { + $invalidLowercaseSymbols += "${filePath}:${lineNumber}: $line" + } + + # Check for strict pattern match + $isValidPattern = $false + foreach ($pattern in $symbolPattern) { + if ($line -match $pattern) { + $isValidPattern = $true + break + } + } + if ($line -match $lowercasePattern -and -not $isValidPattern -and $line -notmatch "^#endif") { + $invalidPatternSymbols += "${filePath}:${lineNumber}: $line" + } + + # Check for uppercase stem + foreach ($config in $symbolConfigs) { + $stem = $config.stem + $upperStem = $stem.ToUpper() + if ($line -match "#(if|if not|elseif)\s+${stem}($rangePattern)" -and $line -cnotmatch "#((?i)(if|if not|elseif))\s+${upperStem}($rangePattern)") { + $invalidStemSymbols += "${filePath}:${lineNumber}: $line" + } + } + } + + if (($invalidLowercaseSymbols.Count -gt 0) -or ($invalidPatternSymbols -gt 0) -or ($invalidStemSymbols -gt 0)) { + return @{ "invalidLowercaseSymbols" = $invalidLowercaseSymbols; "invalidPatternSymbols" = $invalidPatternSymbols; "invalidStemSymbols" = $invalidStemSymbols } + } else { + return $null + } +} + +Export-ModuleMember -Function Test-PreprocessorSymbols \ No newline at end of file diff --git a/build/scripts/tests/TestPreprocessorSymbols.Test.ps1 b/build/scripts/tests/TestPreprocessorSymbols.Test.ps1 new file mode 100644 index 0000000000..de5d6b1413 --- /dev/null +++ b/build/scripts/tests/TestPreprocessorSymbols.Test.ps1 @@ -0,0 +1,304 @@ +Describe "Test-PreprocessorSymbols" { + BeforeAll { + Import-Module "$PSScriptRoot\..\..\..\build\scripts\TestPreprocessorSymbols.psm1" -Force + } + + It 'returns $null when the filepath extension is not .al' { + $result = Test-PreprocessorSymbols -filePath 'Dummy.txt' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 1; 'upperBound' = 1}) + $result | Should -Be $null + } + + It 'returns $null when the file contains lowercase preprocessors with correct symbols and versions' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#if CLEAN1 +#endif + +#if not CLEAN2 +#endif + +#if CLEAN3 +#else +#endif + +#if CLEAN4 +#elseif CLEAN5 +#endif +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 1; 'upperBound' = 5}) + + $result | Should -Be $null + } + + It 'returns $null when the file contains lowercase preprocessors with multiple correct symbolstems and versions' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#if CLEAN1 +#endif + +#if not CLEANSCHEMA2 +#endif + +#if MYSPECIALCASE3 +#else +#endif +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $symbolConfigs = @( + @{stem="CLEAN"; lowerBound=1; upperBound=3}, + @{stem="CLEANSCHEMA"; lowerBound=1; upperBound=3}, + @{stem="MYSPECIALCASE"; lowerBound=1; upperBound=3} + ) + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs $symbolConfigs + + $result | Should -Be $null + } + + It 'returns invalidLowercaseSymbols when the file contains not lowercase preprocessor symbols' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#IF CLEAN1 +#endif + +#if NOT CLEAN2 +#endif + +#if CLEAN3 +#ELSE +#endif + +#if CLEAN4 +#elseif CLEAN5 +#ENDIF + +#If CLEAN6 +#EnDiF + +#iF CLEAN7 +#Else +#EndIf +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 1; 'upperBound' = 7}) + + $result.count | Should -Be 3 + $result.invalidLowercaseSymbols.Count | Should -Be 9 + $result.invalidPatternSymbols.Count | Should -Be 0 + $result.invalidStemSymbols.Count | Should -Be 0 + + $result.invalidLowercaseSymbols | Should -Be @('TestDrive:\dummy.al:3: #IF CLEAN1', 'TestDrive:\dummy.al:6: #if NOT CLEAN2', 'TestDrive:\dummy.al:10: #ELSE', 'TestDrive:\dummy.al:15: #ENDIF', 'TestDrive:\dummy.al:17: #If CLEAN6', 'TestDrive:\dummy.al:18: #EnDiF', 'TestDrive:\dummy.al:20: #iF CLEAN7', 'TestDrive:\dummy.al:21: #Else', 'TestDrive:\dummy.al:22: #EndIf'). + $result.invalidPatternSymbols | Should -Be @(). + $result.invalidStemSymbols | Should -Be @(). + } + + It 'returns invalidPatternSymbols when the spacing is not correct' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +# if CLEAN1 +#endif + +#if not CLEAN2 +#endif + +#if not CLEAN3 +#endif + +#if CLEAN4 +# endif + +#if CLEAN4 +# else +#endif + +#if CLEAN5 +# elseif CLEAN6 +#endif + +#if CLEAN7 +#endif +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 1; 'upperBound' = 7}) + + $result.count | Should -Be 3 + $result.invalidLowercaseSymbols.Count | Should -Be 0 + $result.invalidPatternSymbols.Count | Should -Be 7 + $result.invalidStemSymbols.Count | Should -Be 0 + + $result.invalidLowercaseSymbols | Should -Be @(). + $result.invalidPatternSymbols | Should -Be @('TestDrive:\dummy.al:3: # if CLEAN1', 'TestDrive:\dummy.al:6: #if not CLEAN2', 'TestDrive:\dummy.al:9: #if not CLEAN3', 'TestDrive:\dummy.al:13: # endif', 'TestDrive:\dummy.al:16: # else', 'TestDrive:\dummy.al:20: # elseif CLEAN6', 'TestDrive:\dummy.al:23: #if CLEAN7'). + $result.invalidStemSymbols | Should -Be @(). + } + + It 'returns invalidPatternSymbols when the version is not correct' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#if CLEAN +#endif + +#if CLEAN1 +#endif + +#if not CLEAN2 +#endif + +#if CLEAN3 +#elseif CLEAN4 +#endif + +#if CLEAN8 +#endif + +#if CLEAN12 +#endif + +#if not CLEAN13 +#endif + +#if CLEAN14 +#elseif CLEAN15 +#endif + +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 5; 'upperBound' = 11}) + + $result.count | Should -Be 3 + $result.invalidLowercaseSymbols.Count | Should -Be 0 + $result.invalidPatternSymbols.Count | Should -Be 9 + $result.invalidStemSymbols.Count | Should -Be 0 + + $result.invalidLowercaseSymbols | Should -Be @(). + $result.invalidPatternSymbols | Should -Be @('TestDrive:\dummy.al:3: #if CLEAN', 'TestDrive:\dummy.al:6: #if CLEAN1', 'TestDrive:\dummy.al:9: #if not CLEAN2', 'TestDrive:\dummy.al:12: #if CLEAN3', 'TestDrive:\dummy.al:13: #elseif CLEAN4', 'TestDrive:\dummy.al:19: #if CLEAN12', 'TestDrive:\dummy.al:22: #if not CLEAN13', 'TestDrive:\dummy.al:25: #if CLEAN14', 'TestDrive:\dummy.al:26: #elseif CLEAN15') + $result.invalidStemSymbols | Should -Be @(). + } + + It 'returns invalidPatternSymbols when the symbol stem is not correct' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#if CLEANT1 +#endif + +#if not SCLEAN2 +#endif + +#if SUPERCLEAN3 +#elseif CLEANMORE4 +#endif + +#if FUBAR +#endif + +#if CLEAN7 +#endif + +#if RELEASE +#endif + +#if not RELEASE12 +#endif +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 5; 'upperBound' = 11}) + + $result.count | Should -Be 3 + $result.invalidLowercaseSymbols.Count | Should -Be 0 + $result.invalidPatternSymbols.Count | Should -Be 7 + $result.invalidStemSymbols.Count | Should -Be 0 + + $result.invalidLowercaseSymbols | Should -Be @(). + $result.invalidPatternSymbols | Should -Be @('TestDrive:\dummy.al:3: #if CLEANT1', 'TestDrive:\dummy.al:6: #if not SCLEAN2', 'TestDrive:\dummy.al:9: #if SUPERCLEAN3', 'TestDrive:\dummy.al:10: #elseif CLEANMORE4', 'TestDrive:\dummy.al:13: #if FUBAR', 'TestDrive:\dummy.al:19: #if RELEASE', 'TestDrive:\dummy.al:22: #if not RELEASE12') + $result.invalidStemSymbols | Should -Be @(). + } + + It 'returns invalidStemSymbols when the symbol is not all uppercase' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#if clean1 +#endif + +#if not Clean2 +#endif + +#if ClEaN3 +#else +#endif + +#if cleaN4 +#elseif CleaN5 +#endif +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs @(@{'stem' = "CLEAN"; 'lowerBound' = 1; 'upperBound' = 5}) + + $result.count | Should -Be 3 + $result.invalidLowercaseSymbols.Count | Should -Be 0 + $result.invalidPatternSymbols.Count | Should -Be 0 + $result.invalidStemSymbols.Count | Should -Be 5 + + $result.invalidLowercaseSymbols | Should -Be @(). + $result.invalidPatternSymbols | Should -Be @(). + $result.invalidStemSymbols | Should -Be @('TestDrive:\dummy.al:3: #if clean1', 'TestDrive:\dummy.al:6: #if not Clean2', 'TestDrive:\dummy.al:9: #if ClEaN3', 'TestDrive:\dummy.al:13: #if cleaN4', 'TestDrive:\dummy.al:14: #elseif CleaN5'). + } + + + It 'returns errors' { + $alcontent = @( +'codeunit 123 TestPreprocessors +{ +#if not CLEAN18 +#endif + +# if CLEAN25 +#ELSE +#endif + +#if not CLEANschema22 +#endif + +#if CLEANUP12 +#elseif CLEANSCHEMA34 +#endif +}') + Set-Content -Path TestDrive:\Dummy.al -Value $alcontent + Mock -CommandName Get-Content { return Get-Content TestDrive:\dummy.al} + + $symbolConfigs = @( + @{stem = "CLEAN"; lowerBound = 22; upperBound = 26}, + @{stem = "CLEANSCHEMA"; lowerBound = 15; upperBound = 29} + ) + + $result = Test-PreprocessorSymbols -filePath 'TestDrive:\dummy.al' -symbolConfigs $symbolConfigs + + $result.count | Should -Be 3 + $result.invalidLowercaseSymbols.Count | Should -Be 1 + $result.invalidPatternSymbols.Count | Should -Be 4 + $result.invalidStemSymbols.Count | Should -Be 1 + + $result.invalidLowercaseSymbols | Should -Be @('TestDrive:\dummy.al:7: #ELSE'). + $result.invalidPatternSymbols | Should -Be @('TestDrive:\dummy.al:3: #if not CLEAN18', 'TestDrive:\dummy.al:6: # if CLEAN25', 'TestDrive:\dummy.al:13: #if CLEANUP12', 'TestDrive:\dummy.al:14: #elseif CLEANsCHEMA34'). + $result.invalidStemSymbols | Should -Be @('TestDrive:\dummy.al:10: #if not CLEANschema22'). + } +} diff --git a/build/scripts/tests/runTests.ps1 b/build/scripts/tests/runTests.ps1 new file mode 100644 index 0000000000..0ca5ebd449 --- /dev/null +++ b/build/scripts/tests/runTests.ps1 @@ -0,0 +1,7 @@ +$errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 + +$result = Invoke-Pester @(Get-ChildItem -Path (Join-Path $PSScriptRoot "*.Test.ps1")) -passthru + +if ($result.FailedCount -gt 0) { + throw "$($result.FailedCount) tests are failing" +} \ No newline at end of file diff --git a/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeExt.TableExt.al b/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeExt.TableExt.al index 01b823edd9..2131880597 100644 --- a/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeExt.TableExt.al +++ b/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeExt.TableExt.al @@ -18,6 +18,7 @@ tableextension 230 ObsoleteSourceCodeExt extends "Source Code" MovedTo = '437dbf0e-84ff-417a-965d-ed2bb9650972'; ObsoleteTag = '25.0'; } +#if not CLEANSCHEMA15 field(10620; "SAFT Source Code"; Code[9]) { Caption = 'SAF-T Source Code'; @@ -28,6 +29,7 @@ tableextension 230 ObsoleteSourceCodeExt extends "Source Code" ObsoleteTag = '15.0'; #pragma warning restore AS0072 } +#endif field(28160; Simulation; Boolean) { Caption = 'Simulation'; diff --git a/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeSetupExt.TableExt.al b/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeSetupExt.TableExt.al index 6a8b1a0698..d1bbc321ab 100644 --- a/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeSetupExt.TableExt.al +++ b/src/Business Foundation/App/AuditCodes/src/Legacy/ObsoleteSourceCodeSetupExt.TableExt.al @@ -839,6 +839,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '25.0'; MovedTo = '437dbf0e-84ff-417a-965d-ed2bb9650972'; } +#if not CLEANSCHEMA15 field(11200; "Inward Registration"; Code[10]) { Caption = 'Inward Registration'; @@ -849,6 +850,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '15.0'; #pragma warning restore AS0072 } +#endif field(11307; "Financial Journal"; Code[10]) { Caption = 'Financial Journal'; @@ -879,6 +881,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '25.0'; MovedTo = '437dbf0e-84ff-417a-965d-ed2bb9650972'; } +#if not CLEANSCHEMA20 field(11760; "Purchase VAT Delay"; Code[10]) { Caption = 'Purchase VAT Delay'; @@ -901,6 +904,8 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '20.0'; #pragma warning restore AS0072 } +#endif +#if not CLEANSCHEMA18 field(11762; "VAT Coefficient"; Code[10]) { Caption = 'VAT Coefficient'; @@ -912,6 +917,8 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '18.0'; #pragma warning restore AS0072 } +#endif +#if not CLEANSCHEMA22 field(11764; "Close Balance Sheet"; Code[10]) { Caption = 'Close Balance Sheet'; @@ -934,6 +941,8 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '22.0'; #pragma warning restore AS0072 } +#endif +#if not CLEANSCHEMA20 field(11766; "Cash Desk"; Code[10]) { Caption = 'Cash Desk'; @@ -945,6 +954,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '20.0'; #pragma warning restore AS0072 } +#endif field(12400; "Advance Statements"; Code[10]) { Caption = 'Advance Statements'; @@ -1065,6 +1075,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '25.0'; MovedTo = '437dbf0e-84ff-417a-965d-ed2bb9650972'; } +#if not CLEANSCHEMA21 field(12450; "Item Receipt"; Code[10]) { Caption = 'Item Receipt'; @@ -1087,6 +1098,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '21.0'; #pragma warning restore AS0072 } +#endif field(12470; "FA Release"; Code[10]) { Caption = 'FA Release'; @@ -1147,6 +1159,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '25.0'; MovedTo = '437dbf0e-84ff-417a-965d-ed2bb9650972'; } +#if not CLEANSCHEMA18 field(31041; "Maintenance Adjustment"; Code[10]) { Caption = 'Maintenance Adjustment'; @@ -1158,6 +1171,8 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '18.0'; #pragma warning restore AS0072 } +#endif +#if not CLEANSCHEMA21 field(31050; Credit; Code[10]) { Caption = 'Credit'; @@ -1169,6 +1184,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '21.0'; #pragma warning restore AS0072 } +#endif #pragma warning disable AS0013 field(2000020; "Domiciliation Journal"; Code[10]) { @@ -1190,6 +1206,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '25.0'; MovedTo = '437dbf0e-84ff-417a-965d-ed2bb9650972'; } +#if not CLEANSCHEMA24 field(5005350; "Phys. Invt. Order"; Code[10]) { Caption = 'Phys. Invt. Order'; @@ -1201,6 +1218,7 @@ tableextension 242 ObsoleteSourceCodeSetupExt extends "Source Code Setup" ObsoleteTag = '24.0'; #pragma warning restore AS0072 } +#endif field(7000000; "Cartera Journal"; Code[10]) { Caption = 'Cartera Journal'; diff --git a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineObsolete.TableExt.al b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineObsolete.TableExt.al index e63148c063..89d2b150f1 100644 --- a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineObsolete.TableExt.al +++ b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineObsolete.TableExt.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA27 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -183,4 +184,5 @@ tableextension 309 NoSeriesLineObsolete extends "No. Series Line" end; #endif -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLinePurchase.Table.al b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLinePurchase.Table.al index a96ff1ab44..aa984c2a8d 100644 --- a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLinePurchase.Table.al +++ b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLinePurchase.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA27 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -149,3 +150,4 @@ table 12146 "No. Series Line Purchase" } } } +#endif \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineSales.Table.al b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineSales.Table.al index 51d298860c..099cc9abcd 100644 --- a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineSales.Table.al +++ b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesLineSales.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA27 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -149,3 +150,4 @@ table 12145 "No. Series Line Sales" } } } +#endif \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesObsolete.TableExt.al b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesObsolete.TableExt.al index a3032ddc99..93240995e0 100644 --- a/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesObsolete.TableExt.al +++ b/src/Business Foundation/App/NoSeries/src/Legacy/NoSeriesObsolete.TableExt.al @@ -12,6 +12,7 @@ tableextension 308 NoSeriesObsolete extends "No. Series" { fields { +#if not CLEANSCHEMA18 field(11790; Mask; Text[20]) // CZ Functionality { Caption = 'Mask'; @@ -20,6 +21,7 @@ tableextension 308 NoSeriesObsolete extends "No. Series" ObsoleteState = Removed; ObsoleteTag = '18.0'; } +#endif #pragma warning disable AL0432 field(12100; "No. Series Type"; Integer) #pragma warning restore AL0432 diff --git a/src/System Application/App/Email/src/Message/EmailMessageAttachment.Table.al b/src/System Application/App/Email/src/Message/EmailMessageAttachment.Table.al index 3dd2032ea4..4cf14fc363 100644 --- a/src/System Application/App/Email/src/Message/EmailMessageAttachment.Table.al +++ b/src/System Application/App/Email/src/Message/EmailMessageAttachment.Table.al @@ -25,6 +25,7 @@ table 8904 "Email Message Attachment" DataClassification = SystemMetadata; TableRelation = "Email Message".Id; } +#if not CLEANSCHEMA18 field(3; Attachment; Blob) { DataClassification = CustomerContent; @@ -32,6 +33,7 @@ table 8904 "Email Message Attachment" ObsoleteReason = 'Field has been replaced with the media field, Data.'; ObsoleteTag = '18.1'; } +#endif field(4; "Attachment Name"; Text[250]) { DataClassification = CustomerContent; diff --git a/src/System Application/App/Entity Text/src/AzureOpenAiSettings.Table.al b/src/System Application/App/Entity Text/src/AzureOpenAiSettings.Table.al index 24e83bec7b..e6bce7af18 100644 --- a/src/System Application/App/Entity Text/src/AzureOpenAiSettings.Table.al +++ b/src/System Application/App/Entity Text/src/AzureOpenAiSettings.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA27 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -370,3 +371,4 @@ table 2010 "Azure OpenAi Settings" TelemetryTotalIslandsInvalidTxt: Label 'The total islands config key is not set or is not a number.', Locked = true; #endif } +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Assisted Setup/AggregatedAssistedSetup.Table.al b/src/System Application/App/Guided Experience/src/Assisted Setup/AggregatedAssistedSetup.Table.al index 18a1e88411..b20676bede 100644 --- a/src/System Application/App/Guided Experience/src/Assisted Setup/AggregatedAssistedSetup.Table.al +++ b/src/System Application/App/Guided Experience/src/Assisted Setup/AggregatedAssistedSetup.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA19 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -91,4 +92,4 @@ table 1808 "Aggregated Assisted Setup" } } } - +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetup.Table.al b/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetup.Table.al index 625366ed02..a65f04202a 100644 --- a/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetup.Table.al +++ b/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetup.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -194,4 +195,4 @@ table 1803 "Assisted Setup" Translation.Delete(Rec); end; } - +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupIcons.Table.al b/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupIcons.Table.al index 6abd3d12d4..9487a79a4e 100644 --- a/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupIcons.Table.al +++ b/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupIcons.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA19 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -42,4 +43,4 @@ table 1810 "Assisted Setup Icons" } } } - +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupLog.Table.al b/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupLog.Table.al index 72c4de1b69..81f0493a11 100644 --- a/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupLog.Table.al +++ b/src/System Application/App/Guided Experience/src/Assisted Setup/AssistedSetupLog.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -56,4 +57,4 @@ table 1807 "Assisted Setup Log" } } - +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Assisted Setup/ProductVideoCategory.Table.al b/src/System Application/App/Guided Experience/src/Assisted Setup/ProductVideoCategory.Table.al index d0668d6728..f53199d29b 100644 --- a/src/System Application/App/Guided Experience/src/Assisted Setup/ProductVideoCategory.Table.al +++ b/src/System Application/App/Guided Experience/src/Assisted Setup/ProductVideoCategory.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA19 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -52,4 +53,4 @@ table 1471 "Product Video Category" } } - +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Manual Setup/BusinessSetupIcon.Table.al b/src/System Application/App/Guided Experience/src/Manual Setup/BusinessSetupIcon.Table.al index 8dba446ed2..e62ac36bee 100644 --- a/src/System Application/App/Guided Experience/src/Manual Setup/BusinessSetupIcon.Table.al +++ b/src/System Application/App/Guided Experience/src/Manual Setup/BusinessSetupIcon.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -45,4 +46,4 @@ table 1876 "Business Setup Icon" } } - +#endif \ No newline at end of file diff --git a/src/System Application/App/Guided Experience/src/Manual Setup/ManualSetup.Table.al b/src/System Application/App/Guided Experience/src/Manual Setup/ManualSetup.Table.al index aebf573560..f1c21a7b96 100644 --- a/src/System Application/App/Guided Experience/src/Manual Setup/ManualSetup.Table.al +++ b/src/System Application/App/Guided Experience/src/Manual Setup/ManualSetup.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -77,3 +78,4 @@ table 3700 "Manual Setup" } } #pragma warning restore AS0039 +#endif \ No newline at end of file diff --git a/src/System Application/App/Satisfaction Survey/src/NetPromoterScoreSetup.Table.al b/src/System Application/App/Satisfaction Survey/src/NetPromoterScoreSetup.Table.al index 5f0e39842c..0a0abb1b25 100644 --- a/src/System Application/App/Satisfaction Survey/src/NetPromoterScoreSetup.Table.al +++ b/src/System Application/App/Satisfaction Survey/src/NetPromoterScoreSetup.Table.al @@ -27,6 +27,7 @@ table 1432 "Net Promoter Score Setup" { DataClassification = SystemMetadata; } +#if not CLEANSCHEMA18 field(4; "Time Between Requests"; Integer) { DataClassification = SystemMetadata; @@ -34,6 +35,7 @@ table 1432 "Net Promoter Score Setup" ObsoleteState = Removed; ObsoleteTag = '18.0'; } +#endif field(5; "Request Timeout"; Integer) { DataClassification = SystemMetadata; diff --git a/src/System Application/App/SmartList Designer Subscribers/src/QueryNavigationValidation.Table.al b/src/System Application/App/SmartList Designer Subscribers/src/QueryNavigationValidation.Table.al index 387e796bfc..44552b8385 100644 --- a/src/System Application/App/SmartList Designer Subscribers/src/QueryNavigationValidation.Table.al +++ b/src/System Application/App/SmartList Designer Subscribers/src/QueryNavigationValidation.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -47,3 +48,4 @@ table 2889 "Query Navigation Validation" } } } +#endif \ No newline at end of file diff --git a/src/System Application/App/SmartList Designer Subscribers/src/SmartListDesignerHandler.Table.al b/src/System Application/App/SmartList Designer Subscribers/src/SmartListDesignerHandler.Table.al index f8dc6c15eb..f232641780 100644 --- a/src/System Application/App/SmartList Designer Subscribers/src/SmartListDesignerHandler.Table.al +++ b/src/System Application/App/SmartList Designer Subscribers/src/SmartListDesignerHandler.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -51,4 +52,5 @@ table 2888 "SmartList Designer Handler" Clustered = true; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/System Application/App/User Settings/src/ExtraSettings.Table.al b/src/System Application/App/User Settings/src/ExtraSettings.Table.al index 07b0a77b96..7f1c52f3f8 100644 --- a/src/System Application/App/User Settings/src/ExtraSettings.Table.al +++ b/src/System Application/App/User Settings/src/ExtraSettings.Table.al @@ -1,3 +1,4 @@ +#if not CLEANSCHEMA23 // ------------------------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. @@ -39,4 +40,5 @@ table 9173 "Extra Settings" Clustered = true; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/System Application/App/Video/src/ProductVideoBuffer.Table.al b/src/System Application/App/Video/src/ProductVideoBuffer.Table.al index ad7471592a..f8df4c3fbd 100644 --- a/src/System Application/App/Video/src/ProductVideoBuffer.Table.al +++ b/src/System Application/App/Video/src/ProductVideoBuffer.Table.al @@ -40,6 +40,7 @@ table 1470 "Product Video Buffer" DataClassification = SystemMetadata; Editable = false; } +#if not CLEANSCHEMA18 field(4; "Assisted Setup ID"; Integer) { Caption = 'Assisted Setup ID'; @@ -56,6 +57,7 @@ table 1470 "Product Video Buffer" ObsoleteReason = 'Product videos are no more grouped.'; ObsoleteTag = '18.0'; } +#endif field(6; "Table Num"; Integer) { DataClassification = SystemMetadata;