├── .gitignore ├── scripts ├── GetAllCountries.ps1 ├── BuildTestsWorkSpace.ps1 ├── UpdateALRepo.ps1 └── Auto_load_versions.ps1 ├── .github └── workflows │ └── BuildNewCommits.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ### AL ### 2 | #Template for AL projects for Dynamics 365 Business Central 3 | #launch.json folder 4 | .vscode/ 5 | #Cache folder 6 | .alcache/ 7 | #Symbols folder 8 | .alpackages/ 9 | #Snapshots folder 10 | .snapshots/ 11 | #Testing Output folder 12 | .output/ 13 | #Extension App-file 14 | *.app 15 | #Rapid Application Development File 16 | rad.json 17 | #Translation Base-file 18 | *.g.xlf 19 | #License-file 20 | *.flf 21 | #Test results file 22 | TestResults.xml -------------------------------------------------------------------------------- /scripts/GetAllCountries.ps1: -------------------------------------------------------------------------------- 1 | $countries = [System.Collections.ArrayList]::new() 2 | Get-BCArtifactUrl -select All -Type OnPrem | % { 3 | [System.Uri]$Url = $_ 4 | [version]$Version = $Url.AbsolutePath.Split('/')[2] 5 | if ($Version -ge [version]::Parse('15.0.0.0')) { 6 | $Url.AbsolutePath.Split('/')[3] 7 | } 8 | }| Sort-object -unique | % { $countries.Add($_)} 9 | Write-Output "countries={""countries"":$($countries | ConvertTo-Json -Compress)}" >> $Env:GITHUB_OUTPUT -------------------------------------------------------------------------------- /scripts/BuildTestsWorkSpace.ps1: -------------------------------------------------------------------------------- 1 | $Directories = Get-ChildItem -Directory -Filter "*test*" -Recurse 2 | 3 | $workspace = @{} 4 | $workspace["folders"] = @() 5 | 6 | $Directories | % { 7 | $Childs = Get-ChildItem -Path $_.FullName -Directory -Filter "*test*" 8 | if ($Childs.Count -eq 0 ) { 9 | $path = @{} 10 | $path["path"] = (Get-Item $_.FullName | Resolve-Path -Relative) 11 | 12 | $workspace["folders"] += $path 13 | } 14 | } 15 | 16 | $workspace["settings"] = @{} 17 | 18 | $workspace["settings"]["allint.enabled"] = $false 19 | $workspace["settings"]["al.enableCodeActions"] = $false 20 | $workspace["settings"]["al.enableCodeAnalysis"] = $false 21 | $workspace["settings"]["search.exclude"] = @{"**.xlf" = $true } 22 | 23 | $workspace | ConvertTo-Json | Out-File "test-apps.code-workspace" -Encoding utf8 24 | 25 | -------------------------------------------------------------------------------- /scripts/UpdateALRepo.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | $Localization = '', 3 | $Version = '', 4 | $BuildFolder = '', 5 | $SourcePath, 6 | $RepoPath = '' 7 | ) 8 | 9 | if (-not $SourcePath) { 10 | $SourcePath = "~/.bcartifacts.cache/sandbox/$Version/$Localization/Applications.DE/" 11 | } 12 | 13 | $zips = Get-ChildItem -Path $SourcePath -Filter *.zip -Recurse 14 | Get-ChildItem -Path $RepoPath -Directory -Exclude scripts, .git | Remove-Item -Recurse -Force 15 | 16 | foreach ($zip in $zips) { 17 | $RelativePath = $zip.FullName -ireplace [regex]::Escape($SourcePath + '/'), '' 18 | $ZipTargetPath = Join-Path $RepoPath (Split-Path -Path $RelativePath) 19 | $ZipNameForTarget = (Split-Path -Path $RelativePath -Leaf).Replace('.zip', '').Replace('..Source', '').Replace('.Source', '') 20 | $ZipTargetPath = (Join-Path $ZipTargetPath $ZipNameForTarget) 21 | 7z x $zip.FullName -o"$ZipTargetPath" -r -y | out-null 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/BuildNewCommits.yml: -------------------------------------------------------------------------------- 1 | name: BuildNewCommits 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | prepare: 10 | name: Prepare Matrix 11 | runs-on: ubuntu-latest 12 | 13 | outputs: 14 | countries: ${{ steps.load_countries.outputs.countries }} 15 | 16 | steps: 17 | - name: Install BC Container Helper 18 | shell: pwsh 19 | run: Install-Module bccontainerhelper -force 20 | 21 | - name: Check out the repository to the runner 22 | uses: actions/checkout@v4.1.2 23 | with: 24 | ref: master 25 | 26 | - name: Load Countries 27 | id: load_countries 28 | shell: pwsh 29 | run: ./scripts/GetAllCountries.ps1 30 | 31 | - name: ShowOutput 32 | shell: pwsh 33 | run: Write-Host '${{ steps.load_countries.outputs.countries }}' 34 | 35 | buildCommits: 36 | needs: prepare 37 | name: Build Commits 38 | runs-on: ubuntu-latest 39 | 40 | strategy: 41 | fail-fast: false 42 | matrix: ${{ fromJson(needs.prepare.outputs.countries) }} 43 | 44 | steps: 45 | - name: Install BC Container Helper 46 | shell: pwsh 47 | run: Install-Module bccontainerhelper -force 48 | 49 | - name: Check out the repository to the runner 50 | uses: actions/checkout@v4.2.1 51 | 52 | - name: Build Commits 53 | shell: pwsh 54 | run: | 55 | ./scripts/Auto_load_versions.ps1 -country ${{matrix.countries}} 56 | 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Business Central Code History Repository 2 | 3 | This repository holds all versions of the Buisness Central Apps. The purpose is to quickly be able to compare every version to find changes. 4 | 5 | There is one separate branch per country-major version. 6 | 7 | Go the one of the `w1` branches to find most of the code: 8 | https://github.com/StefanMaron/MSDyn365BC.Code.History/branches/all?query=w1 9 | 10 | Check out the country specific branches to view the localized base app. For example `DE`: 11 | https://github.com/StefanMaron/MSDyn365BC.Code.History/branches/all?query=de 12 | 13 | ## Schedule 14 | 15 | The repository will automatically update itself from the artifacts once a day at midnight UTC 16 | 17 | ## Differences 18 | 19 | Main differences between the old version of the repo: 20 | - the commits are added by pipelines to reduce runtime 21 | - the pipelines will be scheduled to run daily once the initial load is done. 22 | - the main branch is just holding the scripts, switch branch to see the BC Code 23 | - to keep the size of this repo at least in some boundaries, I decided to not include any translation files. 24 | 25 | ## Partial Clone (Subset of Branches) 26 | To reduce the size of the local clone you can use those commands to clone only the branches you need: 27 | 28 | First, clone with those parameters and set it to whatever branch you need: 29 | ``` 30 | git clone -b w1-24 --single-branch https://github.com/StefanMaron/MSDyn365BC.Code.History 31 | ``` 32 | if you want to add additional branches you can do it like this 33 | ``` 34 | git remote set-branches --add origin de-24 35 | git remote set-branches --add origin de-23 36 | git fetch 37 | ``` 38 | You can also use wildcards for [remote-branch], e.g. 39 | ``` 40 | git remote set-branches --add origin us-* 41 | git fetch 42 | ``` 43 | 44 | Removing tracking branches is a little more complicated. 45 | First you need to manually edit the `.git/config` file and remove the branches in the `[remote "origin"]` section 46 | ``` 47 | [core] 48 | repositoryformatversion = 0 49 | filemode = true 50 | bare = false 51 | logallrefupdates = true 52 | [remote "origin"] 53 | url = https://github.com/StefanMaron/MSDyn365BC.Code.History 54 | fetch = +refs/heads/w1-23:refs/remotes/origin/w1-23 55 | fetch = +refs/heads/de-24:refs/remotes/origin/de-24 56 | fetch = +refs/heads/us-*:refs/remotes/origin/us-* 57 | [branch "w1-23"] 58 | remote = origin 59 | merge = refs/heads/w1-23 60 | ``` 61 | once thats done you need to delete the local reference of the remote branches like this 62 | ``` 63 | git branch -d -r origin/us-23 64 | git branch -d -r origin/us-24 65 | ``` 66 | if you had one of those branches checked out locally (a local copy of the branch) you want to delete those as well 67 | ``` 68 | git branch -D us-23 69 | git branch -D us-24 70 | ``` 71 | 72 | and thats it, now `git fetch` should not pull the branches anymore 73 | 74 | ## Partial Clone (Shallow Clone) 75 | To further reduce the size of your local repository, you can also utilize the `--depth` parameter with the `git clone` command. 76 | This creates a shallow clone, fetching only the most recent commits up to the specified depth, thereby ignoring the entire history that you might not need. 77 | 78 | For instance, to clone only the latest commit (depth of 1), you would use the following command: 79 | 80 | ``` 81 | git clone -b w1-24 --depth 1 https://github.com/StefanMaron/MSDyn365BC.Code.History 82 | ``` 83 | 84 | > [!TIP] 85 | > Using `--depth` implies `--single-branch` unless `--no-single-branch` is given to fetch the histories near the tips of all branches. 86 | 87 | Later, you can deepen your clone by 3 commits (or any other number of commits) with `git fetch --deepen 3` or convert it to a complete clone using `git fetch --unshallow`. 88 | 89 | ## Disclaimer 90 | 91 | All code is owned by Microsoft. You can not do any pull request on this repository. 92 | -------------------------------------------------------------------------------- /scripts/Auto_load_versions.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string]$country = 'w1' 3 | ) 4 | 5 | $ErrorActionPreference = "SilentlyContinue" 6 | 7 | [System.Collections.ArrayList]$Versions = @() 8 | Get-BCArtifactUrl -select All -Type OnPrem -country $country -after ([DateTime]::Today.AddDays(-2)) | % { 9 | # Get-BCArtifactUrl -select All -Type OnPrem -country $country | % { 10 | [System.Uri]$Url = $_ 11 | $TempString = $Url.AbsolutePath 12 | [version]$Version = $TempString.Split('/')[2] 13 | $country = $TempString.Split('/')[3] 14 | 15 | [hashtable]$objectProperty = @{} 16 | $objectProperty.Add('Version', $Version) 17 | $objectProperty.Add('Country', $country) 18 | $objectProperty.Add('URL', $Url) 19 | $ourObject = New-Object -TypeName psobject -Property $objectProperty 20 | 21 | if ($Version -ge [version]::Parse('15.0.0.0')) { 22 | $Versions.Add($ourObject) 23 | } 24 | } 25 | 26 | $Versions | Sort-Object -Property Country, Version | % { 27 | [version]$Version = $_.Version 28 | $country = $_.Country.Trim() 29 | Write-Host ($($country)-$($version.ToString())) 30 | 31 | git fetch --all 32 | 33 | $LastCommit = git log --all --grep="^$($country)-$($version.ToString())$" 34 | 35 | if ($LastCommit.Length -eq 0) { 36 | Write-Host "###############################################" 37 | Write-Host "Processing $($country) - $($Version.ToString())" 38 | Write-Host "###############################################" 39 | 40 | $LatestCommitIDOfBranchEmpty = git log -n 1 --pretty=format:"%h" "master" 41 | if ($LatestCommitIDOfBranchEmpty -eq $null) { 42 | $LatestCommitIDOfBranchEmpty = git log -n 1 --pretty=format:"%h" "origin/master" 43 | } 44 | 45 | if ($Version.Major -gt 15 -and $Version.Build -gt 5) { 46 | $CommitIDLastCUFromPreviousMajor = git log --all -n 1 --grep="^$($country)-$($version.Major - 1).5" --pretty=format:"%h" 47 | } 48 | else { 49 | $CommitIDLastCUFromPreviousMajor = $null 50 | } 51 | 52 | $BranchAlreadyExists = ((git branch --list -r "origin/$($country)-$($Version.Major)") -ne $null) -or ((git branch --list "$($country)-$($Version.Major)") -ne $null) 53 | 54 | if ($BranchAlreadyExists) { 55 | git switch "$($country)-$($Version.Major)" 56 | } 57 | else { 58 | if ($CommitIDLastCUFromPreviousMajor -ne $null) { 59 | git switch -c "$($country)-$($Version.Major)" $CommitIDLastCUFromPreviousMajor 60 | } 61 | else { 62 | git switch -c "$($country)-$($Version.Major)" $LatestCommitIDOfBranchEmpty 63 | } 64 | } 65 | 66 | if ($country -eq 'w1'){ 67 | $Paths = Download-Artifacts -artifactUrl $_.URL -includePlatform 68 | $LocalizationPath = $Paths[0] 69 | $PlatformPath = $Paths[1] 70 | } 71 | else { 72 | $Paths = Download-Artifacts -artifactUrl $_.URL 73 | $LocalizationPath = $Paths 74 | $PlatformPath = '' 75 | } 76 | 77 | #Localization folder 78 | 79 | $TargetPathOfVersion = (Join-Path $LocalizationPath (Get-ChildItem -Path $LocalizationPath -filter "Applications")[0].Name) 80 | 81 | if (-not (Test-Path $TargetPathOfVersion)) { 82 | #Platform Folder 83 | $TargetPathOfVersion = (Join-Path $PlatformPath (Get-ChildItem -Path $PlatformPath -filter "Applications")[0].Name) 84 | } 85 | 86 | & "scripts/UpdateALRepo.ps1" -SourcePath $TargetPathOfVersion -RepoPath (Split-Path $PSScriptRoot -Parent) -Version $version -Localization $country 87 | & "scripts/BuildTestsWorkSpace.ps1" 88 | 89 | Get-ChildItem -Recurse -Filter "*.xlf" | Remove-Item 90 | 91 | "$($country)-$($version.ToString())" > version.txt 92 | 93 | git config user.email "stefanmaron@outlook.de" 94 | git config user.name "Stefan Maron" 95 | git add -A | out-null 96 | git commit -a -m "$($country)-$($version.ToString())" | out-null 97 | git gc | out-null 98 | git push --set-upstream origin "$($country)-$($Version.Major)" 99 | 100 | Flush-ContainerHelperCache -keepDays 0 -ErrorAction SilentlyContinue 101 | 102 | Write-Host "$($country)-$($version.ToString())" 103 | } 104 | else { 105 | Write-Host "###############################################" 106 | Write-Host "Skipped version $($country) - $($version.ToString())" 107 | Write-Host "###############################################" 108 | } 109 | } 110 | 111 | 112 | --------------------------------------------------------------------------------