├── .AL-Go ├── cloudDevEnv.ps1 ├── localDevEnv.ps1 └── settings.json ├── .github ├── AL-Go-Settings.json ├── RELEASENOTES.copy.md ├── Test Current.settings.json ├── Test Next Major.settings.json ├── Test Next Minor.settings.json └── workflows │ ├── AddExistingAppOrTestApp.yaml │ ├── CICD.yaml │ ├── CreateApp.yaml │ ├── CreateOnlineDevelopmentEnvironment.yaml │ ├── CreatePerformanceTestApp.yaml │ ├── CreateRelease.yaml │ ├── CreateTestApp.yaml │ ├── Current.yaml │ ├── DeployReferenceDocumentation.yaml │ ├── IncrementVersionNumber.yaml │ ├── NextMajor.yaml │ ├── NextMinor.yaml │ ├── PublishToAppSource.yaml │ ├── PublishToEnvironment.yaml │ ├── PullRequestHandler.yaml │ ├── Troubleshooting.yaml │ ├── UpdateGitHubGoSystemFiles.yaml │ └── _BuildALGoProject.yaml ├── .gitignore ├── App ├── .vscode │ ├── launch.json │ └── settings.json ├── BioDiversityPlant.xlsx ├── BioSample.PermissionSet.al ├── MSAssistedSetupGroup.EnumExt.al ├── MSBioDiversityMgmt.EnumExt.al ├── MSBioDiversityMgmt.PermissionSet.al ├── MSBioDiversityMgmtInsect.Table.al ├── MSBioDiversityMgmtInsectGuide.Page.al ├── MSBioDiversityMgmtInsects.Page.al ├── MSBioDiversityMgmtLocalTest.Codeuit.al ├── MSBioDiversityMgmtPlant.Table.al ├── MSBioDiversityMgmtPlantFamilies.Page.al ├── MSBioDiversityMgmtPlantFamily.Table.al ├── MSBioDiversityMgmtPlantGuide.Page.al ├── MSBioDiversityMgmtPlants.Page.al ├── MSBioDiversityMgmtPlants.Query.al ├── MSBioDiversityMgmtPollinator.Enum.al ├── MSBioDiversityMgmtProfile.Profile.al ├── MSBioDiversityMgmtRoleCenter.Page.al ├── MSBioDiversityMgmtSetup.Page.al ├── MSBioDiversityMgmtSetup.Table.al ├── MSBioDiversityMgmtSetupGuide.Page.al ├── MSBioDiversityMgmtSetupList.Codeunit.al ├── MSBioDiversityMgmtWelcomeExperience.Codeunit.al ├── MSBioDiversityPlant.Report.al ├── app.json └── plants.json ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Media ├── Github Sample Banner │ └── Sample banner.png ├── Logo │ └── logo.png ├── Resources │ ├── wizardbanner.jpg │ └── wizardbanner.png └── Screenshots │ ├── ChecklistItemFromProfiling1.png │ ├── ChecklistItemFromProfiling2.png │ ├── ChecklistItemFromProfiling3.png │ └── ModifyWelcomeBannerTexts.png ├── README.md ├── SECURITY.md ├── SUPPORT.md └── al.code-workspace /.AL-Go/cloudDevEnv.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Script for creating cloud development environment 3 | # Please do not modify this script as it will be auto-updated from the AL-Go Template 4 | # Recommended approach is to use as is or add a script (freddyk-devenv.ps1), which calls this script with the user specific parameters 5 | # 6 | Param( 7 | [string] $environmentName = "", 8 | [bool] $reuseExistingEnvironment, 9 | [switch] $fromVSCode, 10 | [switch] $clean 11 | ) 12 | 13 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 14 | 15 | function DownloadHelperFile { 16 | param( 17 | [string] $url, 18 | [string] $folder 19 | ) 20 | 21 | $prevProgressPreference = $ProgressPreference; $ProgressPreference = 'SilentlyContinue' 22 | $name = [System.IO.Path]::GetFileName($url) 23 | Write-Host "Downloading $name from $url" 24 | $path = Join-Path $folder $name 25 | Invoke-WebRequest -UseBasicParsing -uri $url -OutFile $path 26 | $ProgressPreference = $prevProgressPreference 27 | return $path 28 | } 29 | 30 | try { 31 | Clear-Host 32 | Write-Host 33 | Write-Host -ForegroundColor Yellow @' 34 | _____ _ _ _____ ______ 35 | / ____| | | | | __ \ | ____| 36 | | | | | ___ _ _ __| | | | | | _____ __ |__ _ ____ __ 37 | | | | |/ _ \| | | |/ _` | | | | |/ _ \ \ / / __| | '_ \ \ / / 38 | | |____| | (_) | |_| | (_| | | |__| | __/\ V /| |____| | | \ V / 39 | \_____|_|\___/ \__,_|\__,_| |_____/ \___| \_/ |______|_| |_|\_/ 40 | 41 | '@ 42 | 43 | $tmpFolder = Join-Path ([System.IO.Path]::GetTempPath()) "$([Guid]::NewGuid().ToString())" 44 | New-Item -Path $tmpFolder -ItemType Directory -Force | Out-Null 45 | $GitHubHelperPath = DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/Github-Helper.psm1' -folder $tmpFolder 46 | $ALGoHelperPath = DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/AL-Go-Helper.ps1' -folder $tmpFolder 47 | DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/Packages.json' -folder $tmpFolder | Out-Null 48 | 49 | Import-Module $GitHubHelperPath 50 | . $ALGoHelperPath -local 51 | 52 | $baseFolder = GetBaseFolder -folder $PSScriptRoot 53 | $project = GetProject -baseFolder $baseFolder -projectALGoFolder $PSScriptRoot 54 | 55 | Write-Host @' 56 | 57 | This script will create a cloud based development environment (Business Central SaaS Sandbox) for your project. 58 | All apps and test apps will be compiled and published to the environment in the development scope. 59 | The script will also modify launch.json to have a "Cloud Sandbox ()" configuration point to your environment. 60 | 61 | '@ 62 | 63 | if (Test-Path (Join-Path $PSScriptRoot "NewBcContainer.ps1")) { 64 | Write-Host -ForegroundColor Red "WARNING: The project has a NewBcContainer override defined. Typically, this means that you cannot run a cloud development environment" 65 | } 66 | 67 | Write-Host 68 | 69 | if (-not $environmentName) { 70 | $environmentName = Enter-Value ` 71 | -title "Environment name" ` 72 | -question "Please enter the name of the environment to create" ` 73 | -default "$($env:USERNAME)-sandbox" ` 74 | -trimCharacters @('"',"'",' ') 75 | } 76 | 77 | if ($PSBoundParameters.Keys -notcontains 'reuseExistingEnvironment') { 78 | $reuseExistingEnvironment = (Select-Value ` 79 | -title "What if the environment already exists?" ` 80 | -options @{ "Yes" = "Reuse existing environment"; "No" = "Recreate environment" } ` 81 | -question "Select behavior" ` 82 | -default "No") -eq "Yes" 83 | } 84 | 85 | CreateDevEnv ` 86 | -kind cloud ` 87 | -caller local ` 88 | -environmentName $environmentName ` 89 | -reuseExistingEnvironment:$reuseExistingEnvironment ` 90 | -baseFolder $baseFolder ` 91 | -project $project ` 92 | -clean:$clean 93 | } 94 | catch { 95 | Write-Host -ForegroundColor Red "Error: $($_.Exception.Message)`nStacktrace: $($_.scriptStackTrace)" 96 | } 97 | finally { 98 | if ($fromVSCode) { 99 | Read-Host "Press ENTER to close this window" 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /.AL-Go/localDevEnv.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Script for creating local development environment 3 | # Please do not modify this script as it will be auto-updated from the AL-Go Template 4 | # Recommended approach is to use as is or add a script (freddyk-devenv.ps1), which calls this script with the user specific parameters 5 | # 6 | Param( 7 | [string] $containerName = "", 8 | [ValidateSet("UserPassword", "Windows")] 9 | [string] $auth = "", 10 | [pscredential] $credential = $null, 11 | [string] $licenseFileUrl = "", 12 | [switch] $fromVSCode, 13 | [switch] $accept_insiderEula, 14 | [switch] $clean 15 | ) 16 | 17 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 18 | 19 | function DownloadHelperFile { 20 | param( 21 | [string] $url, 22 | [string] $folder 23 | ) 24 | 25 | $prevProgressPreference = $ProgressPreference; $ProgressPreference = 'SilentlyContinue' 26 | $name = [System.IO.Path]::GetFileName($url) 27 | Write-Host "Downloading $name from $url" 28 | $path = Join-Path $folder $name 29 | Invoke-WebRequest -UseBasicParsing -uri $url -OutFile $path 30 | $ProgressPreference = $prevProgressPreference 31 | return $path 32 | } 33 | 34 | try { 35 | Clear-Host 36 | Write-Host 37 | Write-Host -ForegroundColor Yellow @' 38 | _ _ _____ ______ 39 | | | | | | __ \ | ____| 40 | | | ___ ___ __ _| | | | | | _____ __ |__ _ ____ __ 41 | | | / _ \ / __/ _` | | | | | |/ _ \ \ / / __| | '_ \ \ / / 42 | | |____ (_) | (__ (_| | | | |__| | __/\ V /| |____| | | \ V / 43 | |______\___/ \___\__,_|_| |_____/ \___| \_/ |______|_| |_|\_/ 44 | 45 | '@ 46 | 47 | $tmpFolder = Join-Path ([System.IO.Path]::GetTempPath()) "$([Guid]::NewGuid().ToString())" 48 | New-Item -Path $tmpFolder -ItemType Directory -Force | Out-Null 49 | $GitHubHelperPath = DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/Github-Helper.psm1' -folder $tmpFolder 50 | $ALGoHelperPath = DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/AL-Go-Helper.ps1' -folder $tmpFolder 51 | DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/Packages.json' -folder $tmpFolder | Out-Null 52 | 53 | Import-Module $GitHubHelperPath 54 | . $ALGoHelperPath -local 55 | 56 | $baseFolder = GetBaseFolder -folder $PSScriptRoot 57 | $project = GetProject -baseFolder $baseFolder -projectALGoFolder $PSScriptRoot 58 | 59 | Write-Host @' 60 | 61 | This script will create a docker based local development environment for your project. 62 | 63 | NOTE: You need to have Docker installed, configured and be able to create Business Central containers for this to work. 64 | If this fails, you can setup a cloud based development environment by running cloudDevEnv.ps1 65 | 66 | All apps and test apps will be compiled and published to the environment in the development scope. 67 | The script will also modify launch.json to have a Local Sandbox configuration point to your environment. 68 | 69 | '@ 70 | 71 | $settings = ReadSettings -baseFolder $baseFolder -project $project -userName $env:USERNAME -workflowName 'localDevEnv' 72 | 73 | Write-Host "Checking System Requirements" 74 | $dockerProcess = (Get-Process "dockerd" -ErrorAction Ignore) 75 | if (!($dockerProcess)) { 76 | Write-Host -ForegroundColor Red "Dockerd process not found. Docker might not be started, not installed or not running Windows Containers." 77 | } 78 | if ($settings.keyVaultName) { 79 | if (-not (Get-Module -ListAvailable -Name 'Az.KeyVault')) { 80 | Write-Host -ForegroundColor Red "A keyvault name is defined in Settings, you need to have the Az.KeyVault PowerShell module installed (use Install-Module az) or you can set the keyVaultName to an empty string in the user settings file ($($ENV:UserName).settings.json)." 81 | } 82 | } 83 | 84 | Write-Host 85 | 86 | if (-not $containerName) { 87 | $containerName = Enter-Value ` 88 | -title "Container name" ` 89 | -question "Please enter the name of the container to create" ` 90 | -default "bcserver" ` 91 | -trimCharacters @('"',"'",' ') 92 | } 93 | 94 | if (-not $auth) { 95 | $auth = Select-Value ` 96 | -title "Authentication mechanism for container" ` 97 | -options @{ "Windows" = "Windows Authentication"; "UserPassword" = "Username/Password authentication" } ` 98 | -question "Select authentication mechanism for container" ` 99 | -default "UserPassword" 100 | } 101 | 102 | if (-not $credential) { 103 | if ($auth -eq "Windows") { 104 | $credential = Get-Credential -Message "Please enter your Windows Credentials" -UserName $env:USERNAME 105 | $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName 106 | $domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$credential.UserName,$credential.GetNetworkCredential().password) 107 | if ($null -eq $domain.name) { 108 | Write-Host -ForegroundColor Red "Unable to verify your Windows Credentials, you might not be able to authenticate to your container" 109 | } 110 | } 111 | else { 112 | $credential = Get-Credential -Message "Please enter username and password for your container" -UserName "admin" 113 | } 114 | } 115 | 116 | if (-not $licenseFileUrl) { 117 | if ($settings.type -eq "AppSource App") { 118 | $description = "When developing AppSource Apps for Business Central versions prior to 22, your local development environment needs the developer licensefile with permissions to your AppSource app object IDs" 119 | $default = "none" 120 | } 121 | else { 122 | $description = "When developing PTEs, you can optionally specify a developer licensefile with permissions to object IDs of your dependant apps" 123 | $default = "none" 124 | } 125 | 126 | $licenseFileUrl = Enter-Value ` 127 | -title "LicenseFileUrl" ` 128 | -description $description ` 129 | -question "Local path or a secure download URL to license file " ` 130 | -default $default ` 131 | -doNotConvertToLower ` 132 | -trimCharacters @('"',"'",' ') 133 | } 134 | 135 | if ($licenseFileUrl -eq "none") { 136 | $licenseFileUrl = "" 137 | } 138 | 139 | CreateDevEnv ` 140 | -kind local ` 141 | -caller local ` 142 | -containerName $containerName ` 143 | -baseFolder $baseFolder ` 144 | -project $project ` 145 | -auth $auth ` 146 | -credential $credential ` 147 | -licenseFileUrl $licenseFileUrl ` 148 | -accept_insiderEula:$accept_insiderEula ` 149 | -clean:$clean 150 | } 151 | catch { 152 | Write-Host -ForegroundColor Red "Error: $($_.Exception.Message)`nStacktrace: $($_.scriptStackTrace)" 153 | } 154 | finally { 155 | if ($fromVSCode) { 156 | Read-Host "Press ENTER to close this window" 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /.AL-Go/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "country": "us", 3 | "appSourceCopMandatoryAffixes": [ 4 | "MS_" 5 | ], 6 | "appFolders": [], 7 | "testFolders": [], 8 | "bcptTestFolders": [], 9 | "AppSourceProductId": "e7b625e8-c7b8-45bf-8985-99c69fd53c5e", 10 | "AppSourceContinuousDelivery": true 11 | } 12 | -------------------------------------------------------------------------------- /.github/AL-Go-Settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "AppSource App", 3 | "templateUrl": "https://github.com/microsoft/AL-Go-AppSource@preview" 4 | } 5 | -------------------------------------------------------------------------------- /.github/Test Current.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifact": "////latest", 3 | "cacheImageName": "", 4 | "versioningStrategy": 15 5 | } 6 | -------------------------------------------------------------------------------- /.github/Test Next Major.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifact": "////nextmajor/{INSIDERSASTOKEN}", 3 | "cacheImageName": "", 4 | "versioningStrategy": 15 5 | } 6 | -------------------------------------------------------------------------------- /.github/Test Next Minor.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifact": "////nextminor/{INSIDERSASTOKEN}", 3 | "cacheImageName": "", 4 | "versioningStrategy": 15 5 | } 6 | -------------------------------------------------------------------------------- /.github/workflows/AddExistingAppOrTestApp.yaml: -------------------------------------------------------------------------------- 1 | name: 'Add existing app or test app' 2 | 3 | run-name: "Add existing app or test app in [${{ github.ref_name }}]" 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | project: 9 | description: Project name if the repository is setup for multiple projects 10 | required: false 11 | default: '.' 12 | url: 13 | description: Direct Download Url of .app or .zip file 14 | required: true 15 | directCommit: 16 | description: Direct Commit? 17 | type: boolean 18 | default: false 19 | useGhTokenWorkflow: 20 | description: Use GhTokenWorkflow for PR/Commit? 21 | type: boolean 22 | default: false 23 | 24 | permissions: 25 | actions: read 26 | contents: write 27 | id-token: write 28 | pull-requests: write 29 | 30 | defaults: 31 | run: 32 | shell: powershell 33 | 34 | env: 35 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 36 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 37 | 38 | jobs: 39 | AddExistingAppOrTestApp: 40 | needs: [ ] 41 | runs-on: [ windows-latest ] 42 | steps: 43 | - name: Dump Workflow Information 44 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 45 | with: 46 | shell: powershell 47 | 48 | - name: Checkout 49 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 50 | 51 | - name: Initialize the workflow 52 | id: init 53 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 54 | with: 55 | shell: powershell 56 | 57 | - name: Read settings 58 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 59 | with: 60 | shell: powershell 61 | 62 | - name: Read secrets 63 | id: ReadSecrets 64 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 65 | with: 66 | shell: powershell 67 | gitHubSecrets: ${{ toJson(secrets) }} 68 | getSecrets: 'TokenForPush' 69 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 70 | 71 | - name: Add existing app 72 | uses: microsoft/AL-Go-Actions/AddExistingApp@v7.1 73 | with: 74 | shell: powershell 75 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 76 | project: ${{ github.event.inputs.project }} 77 | url: ${{ github.event.inputs.url }} 78 | directCommit: ${{ github.event.inputs.directCommit }} 79 | 80 | - name: Finalize the workflow 81 | if: always() 82 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 83 | env: 84 | GITHUB_TOKEN: ${{ github.token }} 85 | with: 86 | shell: powershell 87 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 88 | currentJobContext: ${{ toJson(job) }} 89 | -------------------------------------------------------------------------------- /.github/workflows/CICD.yaml: -------------------------------------------------------------------------------- 1 | name: ' CI/CD' 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | paths-ignore: 7 | - '**.md' 8 | - '.github/workflows/*.yaml' 9 | - '!.github/workflows/CICD.yaml' 10 | branches: [ 'main', 'release/*', 'feature/*' ] 11 | 12 | defaults: 13 | run: 14 | shell: powershell 15 | 16 | permissions: 17 | actions: read 18 | contents: read 19 | id-token: write 20 | pages: read 21 | 22 | env: 23 | workflowDepth: 1 24 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 25 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 26 | 27 | jobs: 28 | Initialization: 29 | needs: [ ] 30 | runs-on: [ windows-latest ] 31 | outputs: 32 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 33 | environmentsMatrixJson: ${{ steps.DetermineDeploymentEnvironments.outputs.EnvironmentsMatrixJson }} 34 | environmentCount: ${{ steps.DetermineDeploymentEnvironments.outputs.EnvironmentCount }} 35 | deploymentEnvironmentsJson: ${{ steps.DetermineDeploymentEnvironments.outputs.DeploymentEnvironmentsJson }} 36 | generateALDocArtifact: ${{ steps.DetermineDeploymentEnvironments.outputs.GenerateALDocArtifact }} 37 | deployALDocArtifact: ${{ steps.DetermineDeploymentEnvironments.outputs.DeployALDocArtifact }} 38 | deliveryTargetsJson: ${{ steps.DetermineDeliveryTargets.outputs.DeliveryTargetsJson }} 39 | githubRunner: ${{ steps.ReadSettings.outputs.GitHubRunnerJson }} 40 | githubRunnerShell: ${{ steps.ReadSettings.outputs.GitHubRunnerShell }} 41 | projects: ${{ steps.determineProjectsToBuild.outputs.ProjectsJson }} 42 | skippedProjects: ${{ steps.determineProjectsToBuild.outputs.SkippedProjectsJson }} 43 | projectDependenciesJson: ${{ steps.determineProjectsToBuild.outputs.ProjectDependenciesJson }} 44 | buildOrderJson: ${{ steps.determineProjectsToBuild.outputs.BuildOrderJson }} 45 | baselineWorkflowRunId: ${{ steps.determineProjectsToBuild.outputs.BaselineWorkflowRunId }} 46 | baselineWorkflowSHA: ${{ steps.determineProjectsToBuild.outputs.BaselineWorkflowSHA }} 47 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 48 | powerPlatformSolutionFolder: ${{ steps.DeterminePowerPlatformSolutionFolder.outputs.powerPlatformSolutionFolder }} 49 | steps: 50 | - name: Dump Workflow Information 51 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 52 | with: 53 | shell: powershell 54 | 55 | - name: Checkout 56 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 57 | with: 58 | lfs: true 59 | 60 | - name: Initialize the workflow 61 | id: init 62 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 63 | with: 64 | shell: powershell 65 | 66 | - name: Read settings 67 | id: ReadSettings 68 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 69 | with: 70 | shell: powershell 71 | get: type,powerPlatformSolutionFolder,useGitSubmodules 72 | 73 | - name: Read submodules token 74 | id: ReadSubmodulesToken 75 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 76 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 77 | with: 78 | shell: powershell 79 | gitHubSecrets: ${{ toJson(secrets) }} 80 | getSecrets: '-gitSubmodulesToken' 81 | 82 | - name: Checkout Submodules 83 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 84 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 85 | with: 86 | lfs: true 87 | submodules: ${{ env.useGitSubmodules }} 88 | token: '${{ fromJson(steps.ReadSubmodulesToken.outputs.Secrets).gitSubmodulesToken }}' 89 | 90 | - name: Determine Workflow Depth 91 | id: DetermineWorkflowDepth 92 | run: | 93 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 94 | 95 | - name: Determine Projects To Build 96 | id: determineProjectsToBuild 97 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v7.1 98 | with: 99 | shell: powershell 100 | maxBuildDepth: ${{ env.workflowDepth }} 101 | 102 | - name: Determine PowerPlatform Solution Folder 103 | id: DeterminePowerPlatformSolutionFolder 104 | if: env.type == 'PTE' 105 | run: | 106 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "powerPlatformSolutionFolder=$($env:powerPlatformSolutionFolder)" 107 | 108 | - name: Determine Delivery Target Secrets 109 | id: DetermineDeliveryTargetSecrets 110 | uses: microsoft/AL-Go-Actions/DetermineDeliveryTargets@v7.1 111 | with: 112 | shell: powershell 113 | projectsJson: '${{ steps.determineProjectsToBuild.outputs.ProjectsJson }}' 114 | checkContextSecrets: 'false' 115 | 116 | - name: Read secrets 117 | id: ReadSecrets 118 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 119 | with: 120 | shell: powershell 121 | gitHubSecrets: ${{ toJson(secrets) }} 122 | getSecrets: ${{ steps.DetermineDeliveryTargetSecrets.outputs.ContextSecrets }} 123 | 124 | - name: Determine Delivery Targets 125 | id: DetermineDeliveryTargets 126 | uses: microsoft/AL-Go-Actions/DetermineDeliveryTargets@v7.1 127 | env: 128 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 129 | with: 130 | shell: powershell 131 | projectsJson: '${{ steps.determineProjectsToBuild.outputs.ProjectsJson }}' 132 | checkContextSecrets: 'true' 133 | 134 | - name: Determine Deployment Environments 135 | id: DetermineDeploymentEnvironments 136 | uses: microsoft/AL-Go-Actions/DetermineDeploymentEnvironments@v7.1 137 | env: 138 | GITHUB_TOKEN: ${{ github.token }} 139 | with: 140 | shell: powershell 141 | getEnvironments: '*' 142 | type: 'CD' 143 | 144 | CheckForUpdates: 145 | needs: [ Initialization ] 146 | runs-on: [ windows-latest ] 147 | steps: 148 | - name: Checkout 149 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 150 | 151 | - name: Read settings 152 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 153 | with: 154 | shell: powershell 155 | get: templateUrl 156 | 157 | - name: Read secrets 158 | id: ReadSecrets 159 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 160 | with: 161 | shell: powershell 162 | gitHubSecrets: ${{ toJson(secrets) }} 163 | getSecrets: 'ghTokenWorkflow' 164 | 165 | - name: Check for updates to AL-Go system files 166 | uses: microsoft/AL-Go-Actions/CheckForUpdates@v7.1 167 | env: 168 | GITHUB_TOKEN: ${{ github.token }} 169 | with: 170 | shell: powershell 171 | templateUrl: ${{ env.templateUrl }} 172 | token: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).ghTokenWorkflow }} 173 | downloadLatest: true 174 | 175 | Build: 176 | needs: [ Initialization ] 177 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 178 | strategy: 179 | matrix: 180 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 181 | fail-fast: false 182 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 183 | uses: ./.github/workflows/_BuildALGoProject.yaml 184 | secrets: inherit 185 | with: 186 | shell: ${{ matrix.githubRunnerShell }} 187 | runsOn: ${{ matrix.githubRunner }} 188 | project: ${{ matrix.project }} 189 | projectName: ${{ matrix.projectName }} 190 | buildMode: ${{ matrix.buildMode }} 191 | skippedProjectsJson: ${{ needs.Initialization.outputs.skippedProjects }} 192 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 193 | baselineWorkflowRunId: ${{ needs.Initialization.outputs.baselineWorkflowRunId }} 194 | baselineWorkflowSHA: ${{ needs.Initialization.outputs.baselineWorkflowSHA }} 195 | secrets: 'licenseFileUrl,codeSignCertificateUrl,*codeSignCertificatePassword,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 196 | signArtifacts: true 197 | useArtifactCache: true 198 | 199 | DeployALDoc: 200 | needs: [ Initialization, Build ] 201 | if: (!cancelled()) && needs.Build.result == 'Success' && needs.Initialization.outputs.generateALDocArtifact == 1 && github.ref_name == 'main' 202 | runs-on: [ windows-latest ] 203 | name: Deploy Reference Documentation 204 | permissions: 205 | contents: read 206 | actions: read 207 | pages: write 208 | id-token: write 209 | environment: 210 | name: github-pages 211 | url: ${{ steps.deployment.outputs.page_url }} 212 | steps: 213 | - name: Checkout 214 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 215 | 216 | - name: Download artifacts 217 | uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 218 | with: 219 | path: '.artifacts' 220 | 221 | - name: Read settings 222 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 223 | with: 224 | shell: powershell 225 | 226 | - name: Setup Pages 227 | if: needs.Initialization.outputs.deployALDocArtifact == 1 228 | uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 229 | 230 | - name: Build Reference Documentation 231 | uses: microsoft/AL-Go-Actions/BuildReferenceDocumentation@v7.1 232 | with: 233 | shell: powershell 234 | artifacts: '.artifacts' 235 | 236 | - name: Upload pages artifact 237 | uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 238 | with: 239 | path: ".aldoc/_site/" 240 | 241 | - name: Deploy to GitHub Pages 242 | if: needs.Initialization.outputs.deployALDocArtifact == 1 243 | id: deployment 244 | uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 245 | 246 | Deploy: 247 | needs: [ Initialization, Build ] 248 | if: (!cancelled()) && (needs.Build.result == 'success' || needs.Build.result == 'skipped') && needs.Initialization.outputs.environmentCount > 0 249 | strategy: ${{ fromJson(needs.Initialization.outputs.environmentsMatrixJson) }} 250 | runs-on: ${{ fromJson(matrix.os) }} 251 | name: Deploy to ${{ matrix.environment }} 252 | defaults: 253 | run: 254 | shell: ${{ matrix.shell }} 255 | environment: 256 | name: ${{ matrix.environment }} 257 | url: ${{ steps.Deploy.outputs.environmentUrl }} 258 | steps: 259 | - name: Checkout 260 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 261 | 262 | - name: Download artifacts 263 | uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 264 | with: 265 | path: '.artifacts' 266 | 267 | - name: Read settings 268 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 269 | with: 270 | shell: ${{ matrix.shell }} 271 | get: type,powerPlatformSolutionFolder 272 | 273 | - name: EnvName 274 | id: envName 275 | run: | 276 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 277 | $envName = '${{ matrix.environment }}'.split(' ')[0] 278 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "envName=$envName" 279 | 280 | - name: Read secrets 281 | id: ReadSecrets 282 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 283 | with: 284 | shell: ${{ matrix.shell }} 285 | gitHubSecrets: ${{ toJson(secrets) }} 286 | getSecrets: '${{ steps.envName.outputs.envName }}-AuthContext,${{ steps.envName.outputs.envName }}_AuthContext,AuthContext' 287 | 288 | - name: Deploy to Business Central 289 | id: Deploy 290 | uses: microsoft/AL-Go-Actions/Deploy@v7.1 291 | env: 292 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 293 | with: 294 | shell: ${{ matrix.shell }} 295 | environmentName: ${{ matrix.environment }} 296 | artifactsFolder: '.artifacts' 297 | type: 'CD' 298 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 299 | 300 | - name: Deploy to Power Platform 301 | if: env.type == 'PTE' && env.powerPlatformSolutionFolder != '' 302 | uses: microsoft/AL-Go-Actions/DeployPowerPlatform@v7.1 303 | env: 304 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 305 | with: 306 | shell: powershell 307 | environmentName: ${{ matrix.environment }} 308 | artifactsFolder: '.artifacts' 309 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 310 | 311 | Deliver: 312 | needs: [ Initialization, Build ] 313 | if: (!cancelled()) && (needs.Build.result == 'success' || needs.Build.result == 'skipped') && needs.Initialization.outputs.deliveryTargetsJson != '[]' 314 | strategy: 315 | matrix: 316 | deliveryTarget: ${{ fromJson(needs.Initialization.outputs.deliveryTargetsJson) }} 317 | fail-fast: false 318 | runs-on: [ windows-latest ] 319 | name: Deliver to ${{ matrix.deliveryTarget }} 320 | steps: 321 | - name: Checkout 322 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 323 | 324 | - name: Download artifacts 325 | uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 326 | with: 327 | path: '.artifacts' 328 | 329 | - name: Read settings 330 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 331 | with: 332 | shell: powershell 333 | 334 | - name: Read secrets 335 | id: ReadSecrets 336 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 337 | with: 338 | shell: powershell 339 | gitHubSecrets: ${{ toJson(secrets) }} 340 | getSecrets: '${{ matrix.deliveryTarget }}Context' 341 | 342 | - name: Deliver 343 | uses: microsoft/AL-Go-Actions/Deliver@v7.1 344 | env: 345 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 346 | with: 347 | shell: powershell 348 | type: 'CD' 349 | projects: ${{ needs.Initialization.outputs.projects }} 350 | deliveryTarget: ${{ matrix.deliveryTarget }} 351 | artifacts: '.artifacts' 352 | 353 | PostProcess: 354 | needs: [ Initialization, Build, Deploy, Deliver, DeployALDoc ] 355 | if: (!cancelled()) 356 | runs-on: [ windows-latest ] 357 | steps: 358 | - name: Checkout 359 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 360 | 361 | - name: Finalize the workflow 362 | id: PostProcess 363 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 364 | env: 365 | GITHUB_TOKEN: ${{ github.token }} 366 | with: 367 | shell: powershell 368 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 369 | currentJobContext: ${{ toJson(job) }} 370 | -------------------------------------------------------------------------------- /.github/workflows/CreateApp.yaml: -------------------------------------------------------------------------------- 1 | name: 'Create a new app' 2 | 3 | run-name: "Create a new app in [${{ github.ref_name }}]" 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | project: 9 | description: Project name if the repository is setup for multiple projects 10 | required: false 11 | default: '.' 12 | name: 13 | description: Name 14 | required: true 15 | publisher: 16 | description: Publisher 17 | required: true 18 | idrange: 19 | description: ID range (from..to) 20 | required: true 21 | sampleCode: 22 | description: Include Sample code? 23 | type: boolean 24 | default: true 25 | directCommit: 26 | description: Direct Commit? 27 | type: boolean 28 | default: false 29 | useGhTokenWorkflow: 30 | description: Use GhTokenWorkflow for PR/Commit? 31 | type: boolean 32 | default: false 33 | 34 | permissions: 35 | actions: read 36 | contents: write 37 | id-token: write 38 | pull-requests: write 39 | 40 | defaults: 41 | run: 42 | shell: powershell 43 | 44 | env: 45 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 46 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 47 | 48 | jobs: 49 | CreateApp: 50 | needs: [ ] 51 | runs-on: [ windows-latest ] 52 | steps: 53 | - name: Dump Workflow Information 54 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 55 | with: 56 | shell: powershell 57 | 58 | - name: Checkout 59 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 60 | 61 | - name: Initialize the workflow 62 | id: init 63 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 64 | with: 65 | shell: powershell 66 | 67 | - name: Read settings 68 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 69 | with: 70 | shell: powershell 71 | get: type 72 | 73 | - name: Read secrets 74 | id: ReadSecrets 75 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 76 | with: 77 | shell: powershell 78 | gitHubSecrets: ${{ toJson(secrets) }} 79 | getSecrets: 'TokenForPush' 80 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 81 | 82 | - name: Creating a new app 83 | uses: microsoft/AL-Go-Actions/CreateApp@v7.1 84 | with: 85 | shell: powershell 86 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 87 | project: ${{ github.event.inputs.project }} 88 | type: ${{ env.type }} 89 | name: ${{ github.event.inputs.name }} 90 | publisher: ${{ github.event.inputs.publisher }} 91 | idrange: ${{ github.event.inputs.idrange }} 92 | sampleCode: ${{ github.event.inputs.sampleCode }} 93 | directCommit: ${{ github.event.inputs.directCommit }} 94 | 95 | - name: Finalize the workflow 96 | if: always() 97 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 98 | env: 99 | GITHUB_TOKEN: ${{ github.token }} 100 | with: 101 | shell: powershell 102 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 103 | currentJobContext: ${{ toJson(job) }} 104 | -------------------------------------------------------------------------------- /.github/workflows/CreateOnlineDevelopmentEnvironment.yaml: -------------------------------------------------------------------------------- 1 | name: ' Create Online Dev. Environment' 2 | 3 | run-name: "Create Online Dev. Environment for [${{ github.ref_name }} / ${{ github.event.inputs.project }}]" 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | project: 9 | description: Project name if the repository is setup for multiple projects 10 | required: false 11 | default: '.' 12 | environmentName: 13 | description: Name of the online environment 14 | required: true 15 | reUseExistingEnvironment: 16 | description: Reuse environment if it exists? 17 | type: boolean 18 | default: false 19 | directCommit: 20 | description: Direct Commit? 21 | type: boolean 22 | default: false 23 | useGhTokenWorkflow: 24 | description: Use GhTokenWorkflow for PR/Commit? 25 | type: boolean 26 | default: false 27 | 28 | permissions: 29 | actions: read 30 | contents: write 31 | id-token: write 32 | pull-requests: write 33 | 34 | defaults: 35 | run: 36 | shell: powershell 37 | 38 | env: 39 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 40 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 41 | 42 | jobs: 43 | Initialization: 44 | needs: [ ] 45 | runs-on: [ windows-latest ] 46 | outputs: 47 | deviceCode: ${{ steps.authenticate.outputs.deviceCode }} 48 | githubRunner: ${{ steps.ReadSettings.outputs.GitHubRunnerJson }} 49 | githubRunnerShell: ${{ steps.ReadSettings.outputs.GitHubRunnerShell }} 50 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 51 | steps: 52 | - name: Dump Workflow Information 53 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 54 | with: 55 | shell: powershell 56 | 57 | - name: Checkout 58 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 59 | 60 | - name: Initialize the workflow 61 | id: init 62 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 63 | with: 64 | shell: powershell 65 | 66 | - name: Read settings 67 | id: ReadSettings 68 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 69 | with: 70 | shell: powershell 71 | 72 | - name: Read secrets 73 | id: ReadSecrets 74 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 75 | with: 76 | shell: powershell 77 | gitHubSecrets: ${{ toJson(secrets) }} 78 | getSecrets: 'adminCenterApiCredentials' 79 | 80 | - name: Check AdminCenterApiCredentials / Initiate Device Login (open to see code) 81 | id: authenticate 82 | run: | 83 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 84 | $settings = $env:Settings | ConvertFrom-Json 85 | if ('${{ fromJson(steps.ReadSecrets.outputs.Secrets).adminCenterApiCredentials }}') { 86 | Write-Host "AdminCenterApiCredentials provided in secret $($settings.adminCenterApiCredentialsSecretName)!" 87 | Add-Content -Encoding UTF8 -path $ENV:GITHUB_STEP_SUMMARY -value "Admin Center Api Credentials was provided in a secret called $($settings.adminCenterApiCredentialsSecretName). Using this information for authentication." 88 | } 89 | else { 90 | Write-Host "AdminCenterApiCredentials not provided, initiating Device Code flow" 91 | $ALGoHelperPath = "$([System.IO.Path]::GetTempFileName()).ps1" 92 | $webClient = New-Object System.Net.WebClient 93 | $webClient.DownloadFile('https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/AL-Go-Helper.ps1', $ALGoHelperPath) 94 | . $ALGoHelperPath 95 | DownloadAndImportBcContainerHelper 96 | $authContext = New-BcAuthContext -includeDeviceLogin -deviceLoginTimeout ([TimeSpan]::FromSeconds(0)) 97 | Add-Content -Encoding UTF8 -path $ENV:GITHUB_STEP_SUMMARY -value "AL-Go needs access to the Business Central Admin Center Api and could not locate a secret called $($settings.adminCenterApiCredentialsSecretName) (https://aka.ms/ALGoSettings#AdminCenterApiCredentialsSecretName)`n`n$($authContext.message)" 98 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "deviceCode=$($authContext.deviceCode)" 99 | } 100 | 101 | CreateDevelopmentEnvironment: 102 | needs: [ Initialization ] 103 | runs-on: ${{ fromJson(needs.Initialization.outputs.githubRunner) }} 104 | defaults: 105 | run: 106 | shell: ${{ needs.Initialization.outputs.githubRunnerShell }} 107 | name: Create Development Environment 108 | env: 109 | deviceCode: ${{ needs.Initialization.outputs.deviceCode }} 110 | steps: 111 | - name: Checkout 112 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 113 | 114 | - name: Read settings 115 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 116 | with: 117 | shell: powershell 118 | 119 | - name: Read secrets 120 | id: ReadSecrets 121 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 122 | with: 123 | shell: powershell 124 | gitHubSecrets: ${{ toJson(secrets) }} 125 | getSecrets: 'adminCenterApiCredentials,TokenForPush' 126 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 127 | 128 | - name: Set AdminCenterApiCredentials 129 | id: SetAdminCenterApiCredentials 130 | run: | 131 | if ($env:deviceCode) { 132 | $adminCenterApiCredentials = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("{""deviceCode"":""$($env:deviceCode)""}")) 133 | } 134 | else { 135 | $adminCenterApiCredentials = '${{ fromJson(steps.ReadSecrets.outputs.Secrets).adminCenterApiCredentials }}' 136 | } 137 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -value "adminCenterApiCredentials=$adminCenterApiCredentials" 138 | 139 | - name: Create Development Environment 140 | uses: microsoft/AL-Go-Actions/CreateDevelopmentEnvironment@v7.1 141 | with: 142 | shell: powershell 143 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 144 | environmentName: ${{ github.event.inputs.environmentName }} 145 | project: ${{ github.event.inputs.project }} 146 | reUseExistingEnvironment: ${{ github.event.inputs.reUseExistingEnvironment }} 147 | directCommit: ${{ github.event.inputs.directCommit }} 148 | adminCenterApiCredentials: ${{ steps.SetAdminCenterApiCredentials.outputs.adminCenterApiCredentials }} 149 | 150 | - name: Finalize the workflow 151 | if: always() 152 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 153 | env: 154 | GITHUB_TOKEN: ${{ github.token }} 155 | with: 156 | shell: powershell 157 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 158 | currentJobContext: ${{ toJson(job) }} 159 | -------------------------------------------------------------------------------- /.github/workflows/CreatePerformanceTestApp.yaml: -------------------------------------------------------------------------------- 1 | name: 'Create a new performance test app' 2 | 3 | run-name: "Create a new performance test app in [${{ github.ref_name }}]" 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | project: 9 | description: Project name if the repository is setup for multiple projects 10 | required: false 11 | default: '.' 12 | name: 13 | description: Name 14 | required: true 15 | default: '.PerformanceTest' 16 | publisher: 17 | description: Publisher 18 | required: true 19 | idrange: 20 | description: ID range 21 | required: true 22 | default: '50000..99999' 23 | sampleCode: 24 | description: Include Sample code? 25 | type: boolean 26 | default: true 27 | sampleSuite: 28 | description: Include Sample BCPT Suite? 29 | type: boolean 30 | default: true 31 | directCommit: 32 | description: Direct Commit? 33 | type: boolean 34 | default: false 35 | useGhTokenWorkflow: 36 | description: Use GhTokenWorkflow for PR/Commit? 37 | type: boolean 38 | default: false 39 | 40 | permissions: 41 | actions: read 42 | contents: write 43 | id-token: write 44 | pull-requests: write 45 | 46 | defaults: 47 | run: 48 | shell: powershell 49 | 50 | env: 51 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 52 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 53 | 54 | jobs: 55 | CreatePerformanceTestApp: 56 | needs: [ ] 57 | runs-on: [ windows-latest ] 58 | steps: 59 | - name: Dump Workflow Information 60 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 61 | with: 62 | shell: powershell 63 | 64 | - name: Checkout 65 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 66 | 67 | - name: Initialize the workflow 68 | id: init 69 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 70 | with: 71 | shell: powershell 72 | 73 | - name: Read settings 74 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 75 | with: 76 | shell: powershell 77 | 78 | - name: Read secrets 79 | id: ReadSecrets 80 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 81 | with: 82 | shell: powershell 83 | gitHubSecrets: ${{ toJson(secrets) }} 84 | getSecrets: 'TokenForPush' 85 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 86 | 87 | - name: Creating a new test app 88 | uses: microsoft/AL-Go-Actions/CreateApp@v7.1 89 | with: 90 | shell: powershell 91 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 92 | project: ${{ github.event.inputs.project }} 93 | type: 'Performance Test App' 94 | name: ${{ github.event.inputs.name }} 95 | publisher: ${{ github.event.inputs.publisher }} 96 | idrange: ${{ github.event.inputs.idrange }} 97 | sampleCode: ${{ github.event.inputs.sampleCode }} 98 | sampleSuite: ${{ github.event.inputs.sampleSuite }} 99 | directCommit: ${{ github.event.inputs.directCommit }} 100 | 101 | - name: Finalize the workflow 102 | if: always() 103 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 104 | env: 105 | GITHUB_TOKEN: ${{ github.token }} 106 | with: 107 | shell: powershell 108 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 109 | currentJobContext: ${{ toJson(job) }} 110 | -------------------------------------------------------------------------------- /.github/workflows/CreateRelease.yaml: -------------------------------------------------------------------------------- 1 | name: ' Create release' 2 | run-name: "Create release - Version ${{ inputs.tag }}" 3 | 4 | concurrency: 5 | group: ${{ github.workflow }} 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | buildVersion: 11 | description: Build version to promote to release (default is latest) 12 | required: false 13 | default: 'latest' 14 | name: 15 | description: Name of this release 16 | required: true 17 | default: '' 18 | tag: 19 | description: Tag of this release (needs to be semantic version string https://semver.org, ex. 1.0.0) 20 | required: true 21 | default: '' 22 | releaseType: 23 | description: Release, prerelease or draft? 24 | type: choice 25 | options: 26 | - Release 27 | - Prerelease 28 | - Draft 29 | default: Release 30 | createReleaseBranch: 31 | description: Create Release Branch? 32 | type: boolean 33 | default: false 34 | releaseBranchPrefix: 35 | description: The prefix for the release branch. Used only if 'Create Release Branch?' is checked. 36 | type: string 37 | default: release/ 38 | updateVersionNumber: 39 | description: New Version Number in main branch. Use Major.Minor (optionally add .Build for versioningstrategy 3) for absolute change, or +1, +0.1 (or +0.0.1 for versioningstrategy 3) incremental change. 40 | required: false 41 | default: '' 42 | skipUpdatingDependencies: 43 | description: Skip updating dependency version numbers in all apps. 44 | type: boolean 45 | default: false 46 | directCommit: 47 | description: Direct Commit? 48 | type: boolean 49 | default: false 50 | useGhTokenWorkflow: 51 | description: Use GhTokenWorkflow for PR/Commit? 52 | type: boolean 53 | default: false 54 | 55 | permissions: 56 | actions: read 57 | contents: write 58 | id-token: write 59 | pull-requests: write 60 | 61 | defaults: 62 | run: 63 | shell: powershell 64 | 65 | env: 66 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 67 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 68 | 69 | jobs: 70 | CreateRelease: 71 | needs: [ ] 72 | runs-on: [ windows-latest ] 73 | outputs: 74 | artifacts: ${{ steps.analyzeartifacts.outputs.artifacts }} 75 | releaseId: ${{ steps.createrelease.outputs.releaseId }} 76 | commitish: ${{ steps.analyzeartifacts.outputs.commitish }} 77 | releaseVersion: ${{ steps.createreleasenotes.outputs.releaseVersion }} 78 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 79 | steps: 80 | - name: Dump Workflow Information 81 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 82 | with: 83 | shell: powershell 84 | 85 | - name: Checkout 86 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 87 | 88 | - name: Initialize the workflow 89 | id: init 90 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 91 | with: 92 | shell: powershell 93 | 94 | - name: Read settings 95 | id: ReadSettings 96 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 97 | with: 98 | shell: powershell 99 | get: templateUrl,repoName,type,powerPlatformSolutionFolder 100 | 101 | - name: Read secrets 102 | id: ReadSecrets 103 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 104 | with: 105 | shell: powershell 106 | gitHubSecrets: ${{ toJson(secrets) }} 107 | getSecrets: 'TokenForPush,ghTokenWorkflow' 108 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 109 | 110 | - name: Determine Projects 111 | id: determineProjects 112 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v7.1 113 | with: 114 | shell: powershell 115 | 116 | - name: Check for updates to AL-Go system files 117 | uses: microsoft/AL-Go-Actions/CheckForUpdates@v7.1 118 | with: 119 | shell: powershell 120 | templateUrl: ${{ env.templateUrl }} 121 | token: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).ghTokenWorkflow }} 122 | downloadLatest: true 123 | 124 | - name: Analyze Artifacts 125 | id: analyzeartifacts 126 | env: 127 | _buildVersion: ${{ github.event.inputs.buildVersion }} 128 | run: | 129 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 130 | $projects = '${{ steps.determineProjects.outputs.ProjectsJson }}' | ConvertFrom-Json 131 | Write-Host "projects:" 132 | $projects | ForEach-Object { Write-Host "- $_" } 133 | if ($env:type -eq "PTE" -and $env:powerPlatformSolutionFolder -ne "") { 134 | Write-Host "PowerPlatformSolution:" 135 | Write-Host "- $($env:powerPlatformSolutionFolder)" 136 | $projects += @($env:powerPlatformSolutionFolder) 137 | } 138 | $include = @() 139 | $sha = '' 140 | $allArtifacts = @() 141 | $page = 1 142 | $headers = @{ 143 | "Authorization" = "token ${{ github.token }}" 144 | "X-GitHub-Api-Version" = "2022-11-28" 145 | "Accept" = "application/vnd.github+json; charset=utf-8" 146 | } 147 | do { 148 | $repoArtifacts = Invoke-RestMethod -UseBasicParsing -Headers $headers -Uri "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/actions/artifacts?per_page=100&page=$page" 149 | $allArtifacts += $repoArtifacts.Artifacts | Where-Object { !$_.expired } 150 | $page++ 151 | } 152 | while ($repoArtifacts.Artifacts.Count -gt 0) 153 | Write-Host "Repo Artifacts count: $($repoArtifacts.total_count)" 154 | Write-Host "Downloaded Artifacts count: $($allArtifacts.Count)" 155 | $projects | ForEach-Object { 156 | $thisProject = $_ 157 | if ($thisProject -and ($thisProject -ne '.')) { 158 | $project = $thisProject.Replace('\','_').Replace('/','_') 159 | } 160 | else { 161 | $project = $env:repoName 162 | } 163 | $refname = "$ENV:GITHUB_REF_NAME".Replace('/','_') 164 | Write-Host "Analyzing artifacts for project $project" 165 | $buildVersion = "$env:_buildVersion" 166 | if ($buildVersion -eq "latest") { 167 | Write-Host "Grab latest" 168 | $artifact = $allArtifacts | Where-Object { $_.name -like "$project-$refname-Apps-*.*.*.*" -or $_.name -like "$project-$refname-PowerPlatformSolution-*.*.*.*" } | Select-Object -First 1 169 | } 170 | else { 171 | Write-Host "Search for $project-$refname-Apps-$buildVersion or $project-$refname-PowerPlatformSolution-$buildVersion" 172 | $artifact = $allArtifacts | Where-Object { $_.name -eq "$project-$refname-Apps-$buildVersion"-or $_.name -eq "$project-$refname-PowerPlatformSolution-$buildVersion" } | Select-Object -First 1 173 | } 174 | if ($artifact) { 175 | $startIndex = $artifact.name.LastIndexOf('-') + 1 176 | $artifactsVersion = $artifact.name.SubString($startIndex) 177 | } 178 | else { 179 | Write-Host "::Error::No artifacts found for this project" 180 | exit 1 181 | } 182 | if ($sha) { 183 | if ($artifact.workflow_run.head_sha -ne $sha) { 184 | Write-Host "::Error::The build selected for release doesn't contain all projects. Please rebuild all projects by manually running the CI/CD workflow and recreate the release." 185 | throw "The build selected for release doesn't contain all projects. Please rebuild all projects by manually running the CI/CD workflow and recreate the release." 186 | } 187 | } 188 | else { 189 | $sha = $artifact.workflow_run.head_sha 190 | } 191 | 192 | Write-host "Looking for $project-$refname-Apps-$artifactsVersion or $project-$refname-TestApps-$artifactsVersion or $project-$refname-Dependencies-$artifactsVersion or $project-$refname-PowerPlatformSolution-$artifactsVersion" 193 | $allArtifacts | Where-Object { ($_.name -like "$project-$refname-Apps-$artifactsVersion" -or $_.name -like "$project-$refname-TestApps-$artifactsVersion" -or $_.name -like "$project-$refname-Dependencies-$artifactsVersion" -or $_.name -like "$project-$refname-PowerPlatformSolution-$artifactsVersion") } | ForEach-Object { 194 | $atype = $_.name.SubString(0,$_.name.Length-$artifactsVersion.Length-1) 195 | $atype = $atype.SubString($atype.LastIndexOf('-')+1) 196 | $include += $( [ordered]@{ "name" = $_.name; "url" = $_.archive_download_url; "atype" = $atype; "project" = $thisproject } ) 197 | } 198 | if ($include.Count -eq 0) { 199 | Write-Host "::Error::No artifacts found for version $artifactsVersion" 200 | exit 1 201 | } 202 | } 203 | $artifacts = @{ "include" = $include } 204 | $artifactsJson = $artifacts | ConvertTo-Json -compress 205 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "artifacts=$artifactsJson" 206 | Write-Host "artifacts=$artifactsJson" 207 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "commitish=$sha" 208 | Write-Host "commitish=$sha" 209 | 210 | - name: Prepare release notes 211 | id: createreleasenotes 212 | uses: microsoft/AL-Go-Actions/CreateReleaseNotes@v7.1 213 | with: 214 | shell: powershell 215 | buildVersion: ${{ github.event.inputs.buildVersion }} 216 | tag_name: ${{ github.event.inputs.tag }} 217 | target_commitish: ${{ steps.analyzeartifacts.outputs.commitish }} 218 | 219 | - name: Create release 220 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 221 | id: createrelease 222 | env: 223 | bodyMD: ${{ steps.createreleasenotes.outputs.releaseNotes }} 224 | with: 225 | github-token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 226 | script: | 227 | var bodyMD = process.env.bodyMD 228 | const createReleaseResponse = await github.rest.repos.createRelease({ 229 | owner: context.repo.owner, 230 | repo: context.repo.repo, 231 | tag_name: '${{ github.event.inputs.tag }}', 232 | name: '${{ github.event.inputs.name }}', 233 | body: bodyMD.replaceAll('\\n','\n').replaceAll('%0A','\n').replaceAll('%0D','\n').replaceAll('%25','%'), 234 | draft: ${{ github.event.inputs.releaseType=='Draft' }}, 235 | prerelease: ${{ github.event.inputs.releaseType=='Prerelease' }}, 236 | make_latest: 'legacy', 237 | target_commitish: '${{ steps.analyzeartifacts.outputs.commitish }}' 238 | }); 239 | const { 240 | data: { id: releaseId, html_url: htmlUrl, upload_url: uploadUrl } 241 | } = createReleaseResponse; 242 | core.setOutput('releaseId', releaseId); 243 | 244 | UploadArtifacts: 245 | needs: [ CreateRelease ] 246 | runs-on: [ windows-latest ] 247 | strategy: 248 | matrix: ${{ fromJson(needs.CreateRelease.outputs.artifacts) }} 249 | fail-fast: true 250 | steps: 251 | - name: Checkout 252 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 253 | 254 | - name: Read settings 255 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 256 | with: 257 | shell: powershell 258 | 259 | - name: Read secrets 260 | id: ReadSecrets 261 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 262 | with: 263 | shell: powershell 264 | gitHubSecrets: ${{ toJson(secrets) }} 265 | getSecrets: 'nuGetContext,storageContext,TokenForPush' 266 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 267 | 268 | - name: Download artifact 269 | run: | 270 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 271 | Write-Host "Downloading artifact ${{ matrix.name}}" 272 | $headers = @{ 273 | "Authorization" = "token ${{ github.token }}" 274 | "X-GitHub-Api-Version" = "2022-11-28" 275 | "Accept" = "application/vnd.github+json" 276 | } 277 | Invoke-WebRequest -UseBasicParsing -Headers $headers -Uri '${{ matrix.url }}' -OutFile '${{ matrix.name }}.zip' 278 | 279 | - name: Upload release artifacts 280 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 281 | env: 282 | releaseId: ${{ needs.createrelease.outputs.releaseId }} 283 | with: 284 | github-token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 285 | script: | 286 | const releaseId = process.env.releaseId 287 | const assetPath = '${{ matrix.name }}.zip' 288 | const assetName = encodeURIComponent('${{ matrix.name }}.zip'.replaceAll(' ','.')).replaceAll('%','') 289 | const fs = require('fs'); 290 | const uploadAssetResponse = await github.rest.repos.uploadReleaseAsset({ 291 | owner: context.repo.owner, 292 | repo: context.repo.repo, 293 | release_id: releaseId, 294 | name: assetName, 295 | data: fs.readFileSync(assetPath) 296 | }); 297 | 298 | - name: Deliver to NuGet 299 | uses: microsoft/AL-Go-Actions/Deliver@v7.1 300 | if: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).nuGetContext != '' }} 301 | env: 302 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 303 | with: 304 | shell: powershell 305 | type: 'Release' 306 | projects: ${{ matrix.project }} 307 | deliveryTarget: 'NuGet' 308 | artifacts: ${{ github.event.inputs.buildVersion }} 309 | atypes: 'Apps,TestApps' 310 | 311 | - name: Deliver to Storage 312 | uses: microsoft/AL-Go-Actions/Deliver@v7.1 313 | if: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).storageContext != '' }} 314 | env: 315 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 316 | with: 317 | shell: powershell 318 | type: 'Release' 319 | projects: ${{ matrix.project }} 320 | deliveryTarget: 'Storage' 321 | artifacts: ${{ github.event.inputs.buildVersion }} 322 | atypes: 'Apps,TestApps,Dependencies' 323 | 324 | CreateReleaseBranch: 325 | needs: [ CreateRelease, UploadArtifacts ] 326 | if: ${{ github.event.inputs.createReleaseBranch=='true' }} 327 | runs-on: [ windows-latest ] 328 | steps: 329 | - name: Checkout 330 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 331 | with: 332 | ref: '${{ needs.createRelease.outputs.commitish }}' 333 | 334 | - name: Create Release Branch 335 | env: 336 | releaseBranchPrefix: ${{ github.event.inputs.releaseBranchPrefix }} 337 | run: | 338 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 339 | $releaseBranch = "$($env:releaseBranchPrefix)" + "${{ needs.CreateRelease.outputs.releaseVersion }}" 340 | Write-Host "Creating release branch $releaseBranch" 341 | git checkout -b $releaseBranch 342 | git config user.name ${{ github.actor}} 343 | git config user.email ${{ github.actor}}@users.noreply.github.com 344 | git commit --allow-empty -m "Release branch $releaseBranch" 345 | git push origin $releaseBranch 346 | 347 | UpdateVersionNumber: 348 | needs: [ CreateRelease, UploadArtifacts ] 349 | if: ${{ github.event.inputs.updateVersionNumber!='' }} 350 | runs-on: [ windows-latest ] 351 | steps: 352 | - name: Checkout 353 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 354 | 355 | - name: Read settings 356 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 357 | with: 358 | shell: powershell 359 | 360 | - name: Read secrets 361 | id: ReadSecrets 362 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 363 | with: 364 | shell: powershell 365 | gitHubSecrets: ${{ toJson(secrets) }} 366 | getSecrets: 'TokenForPush' 367 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 368 | 369 | - name: Update Version Number 370 | uses: microsoft/AL-Go-Actions/IncrementVersionNumber@v7.1 371 | with: 372 | shell: powershell 373 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 374 | versionNumber: ${{ github.event.inputs.updateVersionNumber }} 375 | skipUpdatingDependencies: ${{ github.event.inputs.skipUpdatingDependencies }} 376 | directCommit: ${{ github.event.inputs.directCommit }} 377 | 378 | PostProcess: 379 | needs: [ CreateRelease, UploadArtifacts, CreateReleaseBranch, UpdateVersionNumber ] 380 | if: always() 381 | runs-on: [ windows-latest ] 382 | steps: 383 | - name: Checkout 384 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 385 | 386 | - name: Finalize the workflow 387 | id: PostProcess 388 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 389 | env: 390 | GITHUB_TOKEN: ${{ github.token }} 391 | with: 392 | shell: powershell 393 | telemetryScopeJson: ${{ needs.CreateRelease.outputs.telemetryScopeJson }} 394 | currentJobContext: ${{ toJson(job) }} 395 | -------------------------------------------------------------------------------- /.github/workflows/CreateTestApp.yaml: -------------------------------------------------------------------------------- 1 | name: 'Create a new test app' 2 | 3 | run-name: "Create a new test app in [${{ github.ref_name }}]" 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | project: 9 | description: Project name if the repository is setup for multiple projects 10 | required: false 11 | default: '.' 12 | name: 13 | description: Name 14 | required: true 15 | default: '.Test' 16 | publisher: 17 | description: Publisher 18 | required: true 19 | idrange: 20 | description: ID range 21 | required: true 22 | default: '50000..99999' 23 | sampleCode: 24 | description: Include Sample code? 25 | type: boolean 26 | default: true 27 | directCommit: 28 | description: Direct Commit? 29 | type: boolean 30 | default: false 31 | useGhTokenWorkflow: 32 | description: Use GhTokenWorkflow for PR/Commit? 33 | type: boolean 34 | default: false 35 | 36 | permissions: 37 | actions: read 38 | contents: write 39 | id-token: write 40 | pull-requests: write 41 | 42 | defaults: 43 | run: 44 | shell: powershell 45 | 46 | env: 47 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 48 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 49 | 50 | jobs: 51 | CreateTestApp: 52 | needs: [ ] 53 | runs-on: [ windows-latest ] 54 | steps: 55 | - name: Dump Workflow Information 56 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 57 | with: 58 | shell: powershell 59 | 60 | - name: Checkout 61 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 62 | 63 | - name: Initialize the workflow 64 | id: init 65 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 66 | with: 67 | shell: powershell 68 | 69 | - name: Read settings 70 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 71 | with: 72 | shell: powershell 73 | 74 | - name: Read secrets 75 | id: ReadSecrets 76 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 77 | with: 78 | shell: powershell 79 | gitHubSecrets: ${{ toJson(secrets) }} 80 | getSecrets: 'TokenForPush' 81 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 82 | 83 | - name: Creating a new test app 84 | uses: microsoft/AL-Go-Actions/CreateApp@v7.1 85 | with: 86 | shell: powershell 87 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 88 | project: ${{ github.event.inputs.project }} 89 | type: 'Test App' 90 | name: ${{ github.event.inputs.name }} 91 | publisher: ${{ github.event.inputs.publisher }} 92 | idrange: ${{ github.event.inputs.idrange }} 93 | sampleCode: ${{ github.event.inputs.sampleCode }} 94 | directCommit: ${{ github.event.inputs.directCommit }} 95 | 96 | - name: Finalize the workflow 97 | if: always() 98 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 99 | env: 100 | GITHUB_TOKEN: ${{ github.token }} 101 | with: 102 | shell: powershell 103 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 104 | currentJobContext: ${{ toJson(job) }} 105 | -------------------------------------------------------------------------------- /.github/workflows/Current.yaml: -------------------------------------------------------------------------------- 1 | name: ' Test Current' 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | actions: read 8 | contents: read 9 | id-token: write 10 | 11 | defaults: 12 | run: 13 | shell: powershell 14 | 15 | env: 16 | workflowDepth: 1 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | Initialization: 22 | needs: [ ] 23 | runs-on: [ windows-latest ] 24 | outputs: 25 | projects: ${{ steps.determineProjectsToBuild.outputs.ProjectsJson }} 26 | projectDependenciesJson: ${{ steps.determineProjectsToBuild.outputs.ProjectDependenciesJson }} 27 | buildOrderJson: ${{ steps.determineProjectsToBuild.outputs.BuildOrderJson }} 28 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 29 | artifactsRetentionDays: ${{ steps.DetermineWorkflowDepth.outputs.ArtifactsRetentionDays }} 30 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 31 | steps: 32 | - name: Dump Workflow Information 33 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 34 | with: 35 | shell: powershell 36 | 37 | - name: Checkout 38 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 39 | with: 40 | lfs: true 41 | 42 | - name: Initialize the workflow 43 | id: init 44 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 45 | with: 46 | shell: powershell 47 | 48 | - name: Read settings 49 | id: ReadSettings 50 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 51 | with: 52 | shell: powershell 53 | get: useGitSubmodules,shortLivedArtifactsRetentionDays 54 | 55 | - name: Read submodules token 56 | id: ReadSubmodulesToken 57 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 58 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 59 | with: 60 | shell: powershell 61 | gitHubSecrets: ${{ toJson(secrets) }} 62 | getSecrets: '-gitSubmodulesToken' 63 | 64 | - name: Checkout Submodules 65 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 66 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 67 | with: 68 | lfs: true 69 | submodules: ${{ env.useGitSubmodules }} 70 | token: '${{ fromJson(steps.ReadSubmodulesToken.outputs.Secrets).gitSubmodulesToken }}' 71 | 72 | - name: Determine Workflow Depth 73 | id: DetermineWorkflowDepth 74 | run: | 75 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 76 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "ArtifactsRetentionDays=$($env:shortLivedArtifactsRetentionDays)" 77 | 78 | - name: Determine Projects To Build 79 | id: determineProjectsToBuild 80 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v7.1 81 | with: 82 | shell: powershell 83 | maxBuildDepth: ${{ env.workflowDepth }} 84 | 85 | Build: 86 | needs: [ Initialization ] 87 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 88 | strategy: 89 | matrix: 90 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 91 | fail-fast: false 92 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 93 | uses: ./.github/workflows/_BuildALGoProject.yaml 94 | secrets: inherit 95 | with: 96 | shell: ${{ matrix.githubRunnerShell }} 97 | runsOn: ${{ matrix.githubRunner }} 98 | project: ${{ matrix.project }} 99 | projectName: ${{ matrix.projectName }} 100 | buildMode: ${{ matrix.buildMode }} 101 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 102 | secrets: 'licenseFileUrl,codeSignCertificateUrl,*codeSignCertificatePassword,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 103 | artifactsRetentionDays: ${{ fromJson(needs.Initialization.outputs.artifactsRetentionDays) }} 104 | artifactsNameSuffix: 'Current' 105 | 106 | PostProcess: 107 | needs: [ Initialization, Build ] 108 | if: always() 109 | runs-on: [ windows-latest ] 110 | steps: 111 | - name: Checkout 112 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 113 | 114 | - name: Finalize the workflow 115 | id: PostProcess 116 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 117 | env: 118 | GITHUB_TOKEN: ${{ github.token }} 119 | with: 120 | shell: powershell 121 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 122 | currentJobContext: ${{ toJson(job) }} 123 | -------------------------------------------------------------------------------- /.github/workflows/DeployReferenceDocumentation.yaml: -------------------------------------------------------------------------------- 1 | name: ' Deploy Reference Documentation' 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | actions: read 8 | contents: read 9 | id-token: write 10 | pages: write 11 | 12 | defaults: 13 | run: 14 | shell: powershell 15 | 16 | env: 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | DeployALDoc: 22 | runs-on: [ windows-latest ] 23 | name: Deploy Reference Documentation 24 | environment: 25 | name: github-pages 26 | url: ${{ steps.deployment.outputs.page_url }} 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 30 | 31 | - name: Initialize the workflow 32 | id: init 33 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 34 | with: 35 | shell: powershell 36 | 37 | - name: Read settings 38 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 39 | with: 40 | shell: powershell 41 | 42 | - name: Determine Deployment Environments 43 | id: DetermineDeploymentEnvironments 44 | uses: microsoft/AL-Go-Actions/DetermineDeploymentEnvironments@v7.1 45 | env: 46 | GITHUB_TOKEN: ${{ github.token }} 47 | with: 48 | shell: powershell 49 | getEnvironments: 'github-pages' 50 | type: 'Publish' 51 | 52 | - name: Setup Pages 53 | if: steps.DetermineDeploymentEnvironments.outputs.deployALDocArtifact == 1 54 | uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 55 | 56 | - name: Build Reference Documentation 57 | uses: microsoft/AL-Go-Actions/BuildReferenceDocumentation@v7.1 58 | with: 59 | shell: powershell 60 | artifacts: 'latest' 61 | 62 | - name: Upload pages artifact 63 | uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 64 | with: 65 | path: ".aldoc/_site/" 66 | 67 | - name: Deploy to GitHub Pages 68 | if: steps.DetermineDeploymentEnvironments.outputs.deployALDocArtifact == 1 69 | id: deployment 70 | uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 71 | 72 | - name: Finalize the workflow 73 | if: always() 74 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 75 | env: 76 | GITHUB_TOKEN: ${{ github.token }} 77 | with: 78 | shell: powershell 79 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 80 | currentJobContext: ${{ toJson(job) }} 81 | -------------------------------------------------------------------------------- /.github/workflows/IncrementVersionNumber.yaml: -------------------------------------------------------------------------------- 1 | name: ' Increment Version Number' 2 | 3 | run-name: "Increment Version Number in [${{ github.ref_name }}]" 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | projects: 9 | description: Comma-separated list of project name patterns if the repository is setup for multiple projects (default is * for all projects) 10 | required: false 11 | default: '*' 12 | versionNumber: 13 | description: New Version Number in main branch. Use Major.Minor (optionally add .Build for versioningstrategy 3) for absolute change, or +1, +0.1 (or +0.0.1 for versioningstrategy 3) incremental change. 14 | required: false 15 | default: '' 16 | skipUpdatingDependencies: 17 | description: Skip updating dependency version numbers in all apps. 18 | type: boolean 19 | default: false 20 | directCommit: 21 | description: Direct Commit? 22 | type: boolean 23 | default: false 24 | useGhTokenWorkflow: 25 | description: Use GhTokenWorkflow for PR/Commit? 26 | type: boolean 27 | default: false 28 | 29 | defaults: 30 | run: 31 | shell: powershell 32 | 33 | env: 34 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 35 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 36 | 37 | jobs: 38 | IncrementVersionNumber: 39 | needs: [ ] 40 | runs-on: [ windows-latest ] 41 | permissions: 42 | actions: read 43 | contents: write 44 | id-token: write 45 | pull-requests: write 46 | steps: 47 | - name: Dump Workflow Information 48 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 49 | with: 50 | shell: powershell 51 | 52 | - name: Checkout 53 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 54 | 55 | - name: Initialize the workflow 56 | id: init 57 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 58 | with: 59 | shell: powershell 60 | 61 | - name: Read settings 62 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 63 | with: 64 | shell: powershell 65 | 66 | - name: Read secrets 67 | id: ReadSecrets 68 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 69 | with: 70 | shell: powershell 71 | gitHubSecrets: ${{ toJson(secrets) }} 72 | getSecrets: 'TokenForPush' 73 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 74 | 75 | - name: Increment Version Number 76 | uses: microsoft/AL-Go-Actions/IncrementVersionNumber@v7.1 77 | with: 78 | shell: powershell 79 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 80 | projects: ${{ github.event.inputs.projects }} 81 | versionNumber: ${{ github.event.inputs.versionNumber }} 82 | skipUpdatingDependencies: ${{ github.event.inputs.skipUpdatingDependencies }} 83 | directCommit: ${{ github.event.inputs.directCommit }} 84 | 85 | - name: Finalize the workflow 86 | if: always() 87 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 88 | env: 89 | GITHUB_TOKEN: ${{ github.token }} 90 | with: 91 | shell: powershell 92 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 93 | currentJobContext: ${{ toJson(job) }} 94 | -------------------------------------------------------------------------------- /.github/workflows/NextMajor.yaml: -------------------------------------------------------------------------------- 1 | name: ' Test Next Major' 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | actions: read 8 | contents: read 9 | id-token: write 10 | 11 | defaults: 12 | run: 13 | shell: powershell 14 | 15 | env: 16 | workflowDepth: 1 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | Initialization: 22 | needs: [ ] 23 | runs-on: [ windows-latest ] 24 | outputs: 25 | projects: ${{ steps.determineProjectsToBuild.outputs.ProjectsJson }} 26 | projectDependenciesJson: ${{ steps.determineProjectsToBuild.outputs.ProjectDependenciesJson }} 27 | buildOrderJson: ${{ steps.determineProjectsToBuild.outputs.BuildOrderJson }} 28 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 29 | artifactsRetentionDays: ${{ steps.DetermineWorkflowDepth.outputs.ArtifactsRetentionDays }} 30 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 31 | steps: 32 | - name: Dump Workflow Information 33 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 34 | with: 35 | shell: powershell 36 | 37 | - name: Checkout 38 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 39 | with: 40 | lfs: true 41 | 42 | - name: Initialize the workflow 43 | id: init 44 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 45 | with: 46 | shell: powershell 47 | 48 | - name: Read settings 49 | id: ReadSettings 50 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 51 | with: 52 | shell: powershell 53 | get: useGitSubmodules,shortLivedArtifactsRetentionDays 54 | 55 | - name: Read submodules token 56 | id: ReadSubmodulesToken 57 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 58 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 59 | with: 60 | shell: powershell 61 | gitHubSecrets: ${{ toJson(secrets) }} 62 | getSecrets: '-gitSubmodulesToken' 63 | 64 | - name: Checkout Submodules 65 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 66 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 67 | with: 68 | lfs: true 69 | submodules: ${{ env.useGitSubmodules }} 70 | token: '${{ fromJson(steps.ReadSubmodulesToken.outputs.Secrets).gitSubmodulesToken }}' 71 | 72 | - name: Determine Workflow Depth 73 | id: DetermineWorkflowDepth 74 | run: | 75 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 76 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "ArtifactsRetentionDays=$($env:shortLivedArtifactsRetentionDays)" 77 | 78 | - name: Determine Projects To Build 79 | id: determineProjectsToBuild 80 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v7.1 81 | with: 82 | shell: powershell 83 | maxBuildDepth: ${{ env.workflowDepth }} 84 | 85 | Build: 86 | needs: [ Initialization ] 87 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 88 | strategy: 89 | matrix: 90 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 91 | fail-fast: false 92 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 93 | uses: ./.github/workflows/_BuildALGoProject.yaml 94 | secrets: inherit 95 | with: 96 | shell: ${{ matrix.githubRunnerShell }} 97 | runsOn: ${{ matrix.githubRunner }} 98 | project: ${{ matrix.project }} 99 | projectName: ${{ matrix.projectName }} 100 | buildMode: ${{ matrix.buildMode }} 101 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 102 | secrets: 'licenseFileUrl,codeSignCertificateUrl,*codeSignCertificatePassword,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 103 | artifactsRetentionDays: ${{ fromJson(needs.Initialization.outputs.artifactsRetentionDays) }} 104 | artifactsNameSuffix: 'NextMajor' 105 | 106 | PostProcess: 107 | needs: [ Initialization, Build ] 108 | if: always() 109 | runs-on: [ windows-latest ] 110 | steps: 111 | - name: Checkout 112 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 113 | 114 | - name: Finalize the workflow 115 | id: PostProcess 116 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 117 | env: 118 | GITHUB_TOKEN: ${{ github.token }} 119 | with: 120 | shell: powershell 121 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 122 | currentJobContext: ${{ toJson(job) }} 123 | -------------------------------------------------------------------------------- /.github/workflows/NextMinor.yaml: -------------------------------------------------------------------------------- 1 | name: ' Test Next Minor' 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | actions: read 8 | contents: read 9 | id-token: write 10 | 11 | defaults: 12 | run: 13 | shell: powershell 14 | 15 | env: 16 | workflowDepth: 1 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | Initialization: 22 | needs: [ ] 23 | runs-on: [ windows-latest ] 24 | outputs: 25 | projects: ${{ steps.determineProjectsToBuild.outputs.ProjectsJson }} 26 | projectDependenciesJson: ${{ steps.determineProjectsToBuild.outputs.ProjectDependenciesJson }} 27 | buildOrderJson: ${{ steps.determineProjectsToBuild.outputs.BuildOrderJson }} 28 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 29 | artifactsRetentionDays: ${{ steps.DetermineWorkflowDepth.outputs.ArtifactsRetentionDays }} 30 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 31 | steps: 32 | - name: Dump Workflow Information 33 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 34 | with: 35 | shell: powershell 36 | 37 | - name: Checkout 38 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 39 | with: 40 | lfs: true 41 | 42 | - name: Initialize the workflow 43 | id: init 44 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 45 | with: 46 | shell: powershell 47 | 48 | - name: Read settings 49 | id: ReadSettings 50 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 51 | with: 52 | shell: powershell 53 | get: useGitSubmodules,shortLivedArtifactsRetentionDays 54 | 55 | - name: Read submodules token 56 | id: ReadSubmodulesToken 57 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 58 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 59 | with: 60 | shell: powershell 61 | gitHubSecrets: ${{ toJson(secrets) }} 62 | getSecrets: '-gitSubmodulesToken' 63 | 64 | - name: Checkout Submodules 65 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 66 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 67 | with: 68 | lfs: true 69 | submodules: ${{ env.useGitSubmodules }} 70 | token: '${{ fromJson(steps.ReadSubmodulesToken.outputs.Secrets).gitSubmodulesToken }}' 71 | 72 | - name: Determine Workflow Depth 73 | id: DetermineWorkflowDepth 74 | run: | 75 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 76 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "ArtifactsRetentionDays=$($env:shortLivedArtifactsRetentionDays)" 77 | 78 | - name: Determine Projects To Build 79 | id: determineProjectsToBuild 80 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v7.1 81 | with: 82 | shell: powershell 83 | maxBuildDepth: ${{ env.workflowDepth }} 84 | 85 | Build: 86 | needs: [ Initialization ] 87 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 88 | strategy: 89 | matrix: 90 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 91 | fail-fast: false 92 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 93 | uses: ./.github/workflows/_BuildALGoProject.yaml 94 | secrets: inherit 95 | with: 96 | shell: ${{ matrix.githubRunnerShell }} 97 | runsOn: ${{ matrix.githubRunner }} 98 | project: ${{ matrix.project }} 99 | projectName: ${{ matrix.projectName }} 100 | buildMode: ${{ matrix.buildMode }} 101 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 102 | secrets: 'licenseFileUrl,codeSignCertificateUrl,*codeSignCertificatePassword,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 103 | artifactsRetentionDays: ${{ fromJson(needs.Initialization.outputs.artifactsRetentionDays) }} 104 | artifactsNameSuffix: 'NextMinor' 105 | 106 | PostProcess: 107 | needs: [ Initialization, Build ] 108 | if: always() 109 | runs-on: [ windows-latest ] 110 | steps: 111 | - name: Checkout 112 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 113 | 114 | - name: Finalize the workflow 115 | id: PostProcess 116 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 117 | env: 118 | GITHUB_TOKEN: ${{ github.token }} 119 | with: 120 | shell: powershell 121 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 122 | currentJobContext: ${{ toJson(job) }} 123 | -------------------------------------------------------------------------------- /.github/workflows/PublishToAppSource.yaml: -------------------------------------------------------------------------------- 1 | name: ' Publish To AppSource' 2 | run-name: 'Publish To AppSource - Version ${{ inputs.appVersion }}, Projects ${{ inputs.projects }}' 3 | 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | appVersion: 8 | description: App version to deliver to AppSource (current, prerelease, draft, latest or version number) 9 | required: false 10 | default: 'current' 11 | projects: 12 | description: Projects to publish to AppSource if the repository is multi-project. Default is *, which will publish all projects to AppSource. 13 | required: false 14 | default: '*' 15 | GoLive: 16 | description: Promote AppSource App to go live if it passes technical validation? 17 | type: boolean 18 | default: false 19 | 20 | permissions: 21 | actions: read 22 | contents: read 23 | id-token: write 24 | 25 | defaults: 26 | run: 27 | shell: powershell 28 | 29 | env: 30 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 31 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 32 | 33 | jobs: 34 | Initialization: 35 | needs: [ ] 36 | runs-on: [ windows-latest ] 37 | outputs: 38 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 39 | steps: 40 | - name: Dump Workflow Information 41 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 42 | with: 43 | shell: powershell 44 | 45 | - name: Checkout 46 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 47 | 48 | - name: Initialize the workflow 49 | id: init 50 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 51 | with: 52 | shell: powershell 53 | 54 | Deliver: 55 | needs: [ Initialization ] 56 | runs-on: [ windows-latest ] 57 | name: Deliver to AppSource 58 | steps: 59 | - name: Checkout 60 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 61 | 62 | - name: Read settings 63 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 64 | with: 65 | shell: powershell 66 | 67 | - name: Read secrets 68 | id: ReadSecrets 69 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 70 | with: 71 | shell: powershell 72 | gitHubSecrets: ${{ toJson(secrets) }} 73 | getSecrets: 'appSourceContext' 74 | 75 | - name: Deliver 76 | uses: microsoft/AL-Go-Actions/Deliver@v7.1 77 | env: 78 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 79 | with: 80 | shell: powershell 81 | type: 'Release' 82 | projects: ${{ github.event.inputs.projects }} 83 | deliveryTarget: 'AppSource' 84 | artifacts: ${{ github.event.inputs.appVersion }} 85 | goLive: ${{ github.event.inputs.goLive }} 86 | 87 | PostProcess: 88 | needs: [ Initialization, Deliver ] 89 | if: always() 90 | runs-on: [ windows-latest ] 91 | steps: 92 | - name: Checkout 93 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 94 | 95 | - name: Finalize the workflow 96 | id: PostProcess 97 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 98 | env: 99 | GITHUB_TOKEN: ${{ github.token }} 100 | with: 101 | shell: powershell 102 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 103 | currentJobContext: ${{ toJson(job) }} 104 | -------------------------------------------------------------------------------- /.github/workflows/PublishToEnvironment.yaml: -------------------------------------------------------------------------------- 1 | name: ' Publish To Environment' 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | appVersion: 7 | description: App version to deploy to environment(s) (current, prerelease, draft, latest, version number or PR_) 8 | required: false 9 | default: 'current' 10 | environmentName: 11 | description: Environment mask to receive the new version (* for all, PROD* for all environments starting with PROD) 12 | required: true 13 | 14 | permissions: 15 | actions: read 16 | contents: read 17 | id-token: write 18 | 19 | defaults: 20 | run: 21 | shell: powershell 22 | 23 | env: 24 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 25 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 26 | 27 | jobs: 28 | Initialization: 29 | needs: [ ] 30 | runs-on: [ windows-latest ] 31 | outputs: 32 | environmentsMatrixJson: ${{ steps.DetermineDeploymentEnvironments.outputs.EnvironmentsMatrixJson }} 33 | environmentCount: ${{ steps.DetermineDeploymentEnvironments.outputs.EnvironmentCount }} 34 | deploymentEnvironmentsJson: ${{ steps.DetermineDeploymentEnvironments.outputs.DeploymentEnvironmentsJson }} 35 | deviceCode: ${{ steps.Authenticate.outputs.deviceCode }} 36 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 37 | steps: 38 | - name: Dump Workflow Information 39 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 40 | with: 41 | shell: powershell 42 | 43 | - name: Checkout 44 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 45 | 46 | - name: Initialize the workflow 47 | id: init 48 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 49 | with: 50 | shell: powershell 51 | 52 | - name: Read settings 53 | id: ReadSettings 54 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 55 | with: 56 | shell: powershell 57 | 58 | - name: Determine Deployment Environments 59 | id: DetermineDeploymentEnvironments 60 | uses: microsoft/AL-Go-Actions/DetermineDeploymentEnvironments@v7.1 61 | env: 62 | GITHUB_TOKEN: ${{ github.token }} 63 | with: 64 | shell: powershell 65 | getEnvironments: ${{ github.event.inputs.environmentName }} 66 | type: 'Publish' 67 | 68 | - name: EnvName 69 | id: envName 70 | if: steps.DetermineDeploymentEnvironments.outputs.UnknownEnvironment == 1 71 | run: | 72 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 73 | $envName = '${{ fromJson(steps.DetermineDeploymentEnvironments.outputs.environmentsMatrixJson).matrix.include[0].environment }}'.split(' ')[0] 74 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "envName=$envName" 75 | 76 | - name: Read secrets 77 | id: ReadSecrets 78 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 79 | if: steps.DetermineDeploymentEnvironments.outputs.UnknownEnvironment == 1 80 | with: 81 | shell: powershell 82 | gitHubSecrets: ${{ toJson(secrets) }} 83 | getSecrets: '${{ steps.envName.outputs.envName }}-AuthContext,${{ steps.envName.outputs.envName }}_AuthContext,AuthContext' 84 | 85 | - name: Authenticate 86 | id: Authenticate 87 | if: steps.DetermineDeploymentEnvironments.outputs.UnknownEnvironment == 1 88 | run: | 89 | $envName = '${{ steps.envName.outputs.envName }}' 90 | $secretName = '' 91 | $secrets = '${{ steps.ReadSecrets.outputs.Secrets }}' | ConvertFrom-Json 92 | $authContext = $null 93 | "$($envName)-AuthContext", "$($envName)_AuthContext", "AuthContext" | ForEach-Object { 94 | if (!($authContext)) { 95 | if ($secrets."$_") { 96 | Write-Host "Using $_ secret as AuthContext" 97 | $authContext = $secrets."$_" 98 | $secretName = $_ 99 | } 100 | } 101 | } 102 | if ($authContext) { 103 | Write-Host "AuthContext provided in secret $secretName!" 104 | Add-Content -Encoding UTF8 -path $ENV:GITHUB_STEP_SUMMARY -value "AuthContext was provided in a secret called $secretName. Using this information for authentication." 105 | } 106 | else { 107 | Write-Host "No AuthContext provided for $envName, initiating Device Code flow" 108 | $ALGoHelperPath = "$([System.IO.Path]::GetTempFileName()).ps1" 109 | $webClient = New-Object System.Net.WebClient 110 | $webClient.DownloadFile('https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v7.1/AL-Go-Helper.ps1', $ALGoHelperPath) 111 | . $ALGoHelperPath 112 | DownloadAndImportBcContainerHelper 113 | $authContext = New-BcAuthContext -includeDeviceLogin -deviceLoginTimeout ([TimeSpan]::FromSeconds(0)) 114 | Add-Content -Encoding UTF8 -path $ENV:GITHUB_STEP_SUMMARY -value "AL-Go needs access to the Business Central Environment $('${{ steps.envName.outputs.envName }}'.Split(' ')[0]) and could not locate a secret called ${{ steps.envName.outputs.envName }}_AuthContext`n`n$($authContext.message)" 115 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "deviceCode=$($authContext.deviceCode)" 116 | } 117 | 118 | Deploy: 119 | needs: [ Initialization ] 120 | if: needs.Initialization.outputs.environmentCount > 0 121 | strategy: ${{ fromJson(needs.Initialization.outputs.environmentsMatrixJson) }} 122 | runs-on: ${{ fromJson(matrix.os) }} 123 | name: Deploy to ${{ matrix.environment }} 124 | defaults: 125 | run: 126 | shell: ${{ matrix.shell }} 127 | environment: 128 | name: ${{ matrix.environment }} 129 | url: ${{ steps.Deploy.outputs.environmentUrl }} 130 | env: 131 | deviceCode: ${{ needs.Initialization.outputs.deviceCode }} 132 | steps: 133 | - name: Checkout 134 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 135 | 136 | - name: EnvName 137 | id: envName 138 | run: | 139 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 140 | $envName = '${{ matrix.environment }}'.split(' ')[0] 141 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "envName=$envName" 142 | 143 | - name: Read settings 144 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 145 | with: 146 | shell: ${{ matrix.shell }} 147 | get: type,powerPlatformSolutionFolder 148 | 149 | - name: Read secrets 150 | id: ReadSecrets 151 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 152 | with: 153 | shell: ${{ matrix.shell }} 154 | gitHubSecrets: ${{ toJson(secrets) }} 155 | getSecrets: '${{ steps.envName.outputs.envName }}-AuthContext,${{ steps.envName.outputs.envName }}_AuthContext,AuthContext' 156 | 157 | - name: Get Artifacts for deployment 158 | uses: microsoft/AL-Go-Actions/GetArtifactsForDeployment@v7.1 159 | with: 160 | shell: ${{ matrix.shell }} 161 | artifactsVersion: ${{ github.event.inputs.appVersion }} 162 | artifactsFolder: '.artifacts' 163 | 164 | - name: Deploy to Business Central 165 | id: Deploy 166 | uses: microsoft/AL-Go-Actions/Deploy@v7.1 167 | env: 168 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 169 | with: 170 | shell: ${{ matrix.shell }} 171 | environmentName: ${{ matrix.environment }} 172 | artifactsFolder: '.artifacts' 173 | type: 'Publish' 174 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 175 | artifactsVersion: ${{ github.event.inputs.appVersion }} 176 | 177 | - name: Deploy to Power Platform 178 | if: env.type == 'PTE' && env.powerPlatformSolutionFolder != '' 179 | uses: microsoft/AL-Go-Actions/DeployPowerPlatform@v7.1 180 | env: 181 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 182 | with: 183 | shell: ${{ matrix.shell }} 184 | environmentName: ${{ matrix.environment }} 185 | artifactsFolder: '.artifacts' 186 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 187 | 188 | PostProcess: 189 | needs: [ Initialization, Deploy ] 190 | if: always() 191 | runs-on: [ windows-latest ] 192 | steps: 193 | - name: Checkout 194 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 195 | 196 | - name: Finalize the workflow 197 | id: PostProcess 198 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 199 | env: 200 | GITHUB_TOKEN: ${{ github.token }} 201 | with: 202 | shell: powershell 203 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 204 | currentJobContext: ${{ toJson(job) }} 205 | -------------------------------------------------------------------------------- /.github/workflows/PullRequestHandler.yaml: -------------------------------------------------------------------------------- 1 | name: 'Pull Request Build' 2 | 3 | on: 4 | pull_request_target: 5 | branches: [ 'main' ] 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.event.pull_request.number }} 9 | cancel-in-progress: true 10 | 11 | defaults: 12 | run: 13 | shell: powershell 14 | 15 | permissions: 16 | actions: read 17 | contents: read 18 | id-token: write 19 | pull-requests: read 20 | 21 | env: 22 | workflowDepth: 1 23 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 24 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 25 | 26 | jobs: 27 | PregateCheck: 28 | if: (github.event.pull_request.base.repo.full_name != github.event.pull_request.head.repo.full_name) && (github.event_name != 'pull_request') 29 | runs-on: windows-latest 30 | steps: 31 | - uses: microsoft/AL-Go-Actions/VerifyPRChanges@v7.1 32 | 33 | Initialization: 34 | needs: [ PregateCheck ] 35 | if: (!failure() && !cancelled()) 36 | runs-on: [ windows-latest ] 37 | outputs: 38 | projects: ${{ steps.determineProjectsToBuild.outputs.ProjectsJson }} 39 | projectDependenciesJson: ${{ steps.determineProjectsToBuild.outputs.ProjectDependenciesJson }} 40 | buildOrderJson: ${{ steps.determineProjectsToBuild.outputs.BuildOrderJson }} 41 | baselineWorkflowRunId: ${{ steps.determineProjectsToBuild.outputs.BaselineWorkflowRunId }} 42 | baselineWorkflowSHA: ${{ steps.determineProjectsToBuild.outputs.BaselineWorkflowSHA }} 43 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 44 | artifactsRetentionDays: ${{ steps.DetermineWorkflowDepth.outputs.ArtifactsRetentionDays }} 45 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 46 | steps: 47 | - name: Dump Workflow Information 48 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 49 | with: 50 | shell: powershell 51 | 52 | - name: Checkout 53 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 54 | with: 55 | lfs: true 56 | ref: ${{ github.event_name == 'pull_request' && github.sha || format('refs/pull/{0}/merge', github.event.pull_request.number) }} 57 | 58 | - name: Initialize the workflow 59 | id: init 60 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 61 | with: 62 | shell: powershell 63 | 64 | - name: Read settings 65 | id: ReadSettings 66 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 67 | with: 68 | shell: powershell 69 | get: shortLivedArtifactsRetentionDays 70 | 71 | - name: Determine Workflow Depth 72 | id: DetermineWorkflowDepth 73 | run: | 74 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 75 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "ArtifactsRetentionDays=$($env:shortLivedArtifactsRetentionDays)" 76 | 77 | - name: Determine Projects To Build 78 | id: determineProjectsToBuild 79 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v7.1 80 | with: 81 | shell: powershell 82 | maxBuildDepth: ${{ env.workflowDepth }} 83 | 84 | Build: 85 | needs: [ Initialization ] 86 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 87 | strategy: 88 | matrix: 89 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 90 | fail-fast: false 91 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 92 | uses: ./.github/workflows/_BuildALGoProject.yaml 93 | secrets: inherit 94 | with: 95 | shell: ${{ matrix.githubRunnerShell }} 96 | runsOn: ${{ matrix.githubRunner }} 97 | checkoutRef: ${{ github.event_name == 'pull_request' && github.sha || format('refs/pull/{0}/merge', github.event.pull_request.number) }} 98 | project: ${{ matrix.project }} 99 | projectName: ${{ matrix.projectName }} 100 | buildMode: ${{ matrix.buildMode }} 101 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 102 | baselineWorkflowRunId: ${{ needs.Initialization.outputs.baselineWorkflowRunId }} 103 | baselineWorkflowSHA: ${{ needs.Initialization.outputs.baselineWorkflowSHA }} 104 | secrets: 'licenseFileUrl,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 105 | artifactsRetentionDays: ${{ fromJson(needs.Initialization.outputs.artifactsRetentionDays) }} 106 | artifactsNameSuffix: 'PR${{ github.event.number }}' 107 | useArtifactCache: true 108 | 109 | StatusCheck: 110 | needs: [ Initialization, Build ] 111 | if: (!cancelled()) 112 | runs-on: [ windows-latest ] 113 | name: Pull Request Status Check 114 | steps: 115 | - name: Pull Request Status Check 116 | id: PullRequestStatusCheck 117 | uses: microsoft/AL-Go-Actions/PullRequestStatusCheck@v7.1 118 | env: 119 | GITHUB_TOKEN: ${{ github.token }} 120 | with: 121 | shell: powershell 122 | 123 | - name: Finalize the workflow 124 | id: PostProcess 125 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 126 | if: success() || failure() 127 | env: 128 | GITHUB_TOKEN: ${{ github.token }} 129 | with: 130 | shell: powershell 131 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 132 | currentJobContext: ${{ toJson(job) }} 133 | -------------------------------------------------------------------------------- /.github/workflows/Troubleshooting.yaml: -------------------------------------------------------------------------------- 1 | name: 'Troubleshooting' 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | displayNameOfSecrets: 7 | description: Display the name (not the value) of secrets available to the repository 8 | type: boolean 9 | default: false 10 | 11 | permissions: 12 | actions: read 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | shell: powershell 18 | 19 | env: 20 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 21 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 22 | 23 | jobs: 24 | Troubleshooting: 25 | runs-on: [ windows-latest ] 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | with: 30 | lfs: true 31 | 32 | - name: Troubleshooting 33 | uses: microsoft/AL-Go-Actions/Troubleshooting@v7.1 34 | with: 35 | shell: powershell 36 | gitHubSecrets: ${{ toJson(secrets) }} 37 | displayNameOfSecrets: ${{ github.event.inputs.displayNameOfSecrets }} 38 | -------------------------------------------------------------------------------- /.github/workflows/UpdateGitHubGoSystemFiles.yaml: -------------------------------------------------------------------------------- 1 | name: ' Update AL-Go System Files' 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | templateUrl: 7 | description: Template Repository URL (current is https://github.com/microsoft/AL-Go-AppSource@preview) 8 | required: false 9 | default: '' 10 | downloadLatest: 11 | description: Download latest from template repository 12 | type: boolean 13 | default: true 14 | directCommit: 15 | description: Direct Commit? 16 | type: boolean 17 | default: false 18 | includeBranches: 19 | description: Specify a comma-separated list of branches to update. Wildcards are supported. The AL-Go settings will be read for every branch. Leave empty to update the current branch only. 20 | required: false 21 | default: '' 22 | 23 | permissions: 24 | actions: read 25 | contents: read 26 | id-token: write 27 | 28 | defaults: 29 | run: 30 | shell: powershell 31 | 32 | env: 33 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 34 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 35 | 36 | jobs: 37 | Initialize: 38 | runs-on: windows-latest 39 | name: Initialize 40 | outputs: 41 | UpdateBranches: ${{ steps.GetBranches.outputs.Result }} 42 | TemplateUrl: ${{ steps.DetermineTemplateUrl.outputs.TemplateUrl }} 43 | steps: 44 | - name: Checkout 45 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 46 | 47 | - name: Read settings 48 | id: ReadSettings 49 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 50 | with: 51 | shell: powershell 52 | get: templateUrl 53 | 54 | - name: Get Workflow Multi-Run Branches 55 | id: GetBranches 56 | uses: microsoft/AL-Go-Actions/GetWorkflowMultiRunBranches@v7.1 57 | with: 58 | shell: powershell 59 | includeBranches: ${{ github.event.inputs.includeBranches }} 60 | 61 | - name: Determine Template URL 62 | id: DetermineTemplateUrl 63 | env: 64 | TemplateUrlAsInput: '${{ github.event.inputs.templateUrl }}' 65 | run: | 66 | $templateUrl = $env:templateUrl # Available from ReadSettings step 67 | if ($ENV:TemplateUrlAsInput) { 68 | # Use the input value if it is provided 69 | $templateUrl = $ENV:TemplateUrlAsInput 70 | } 71 | Write-Host "Using template URL: $templateUrl" 72 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "TemplateUrl=$templateUrl" 73 | 74 | UpdateALGoSystemFiles: 75 | name: "[${{ matrix.branch }}] Update AL-Go System Files" 76 | needs: [ Initialize ] 77 | runs-on: [ windows-latest ] 78 | strategy: 79 | matrix: 80 | branch: ${{ fromJson(needs.Initialize.outputs.UpdateBranches).branches }} 81 | fail-fast: false 82 | 83 | steps: 84 | - name: Dump Workflow Information 85 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v7.1 86 | with: 87 | shell: powershell 88 | 89 | - name: Checkout 90 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 91 | with: 92 | ref: ${{ matrix.branch }} 93 | 94 | - name: Initialize the workflow 95 | id: init 96 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v7.1 97 | with: 98 | shell: powershell 99 | 100 | - name: Read settings 101 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 102 | with: 103 | shell: powershell 104 | get: commitOptions 105 | 106 | - name: Read secrets 107 | id: ReadSecrets 108 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 109 | with: 110 | shell: powershell 111 | gitHubSecrets: ${{ toJson(secrets) }} 112 | getSecrets: 'ghTokenWorkflow' 113 | 114 | - name: Calculate Commit Options 115 | env: 116 | directCommit: '${{ github.event.inputs.directCommit }}' 117 | downloadLatest: '${{ github.event.inputs.downloadLatest }}' 118 | run: | 119 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 120 | if('${{ github.event_name }}' -eq 'workflow_dispatch') { 121 | Write-Host "Using inputs from workflow_dispatch event" 122 | $directCommit = $env:directCommit 123 | $downloadLatest = $env:downloadLatest 124 | } 125 | else { 126 | Write-Host "Using inputs from commitOptions setting" 127 | $commitOptions = $env:commitOptions | ConvertFrom-Json # Available from ReadSettings step 128 | $directCommit=$(-not $commitOptions.createPullRequest) 129 | $downloadLatest=$true 130 | } 131 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "directCommit=$directCommit" 132 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "downloadLatest=$downloadLatest" 133 | 134 | - name: Update AL-Go system files 135 | uses: microsoft/AL-Go-Actions/CheckForUpdates@v7.1 136 | env: 137 | GITHUB_TOKEN: ${{ github.token }} 138 | with: 139 | shell: powershell 140 | token: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).ghTokenWorkflow }} 141 | downloadLatest: ${{ env.downloadLatest }} 142 | update: 'Y' 143 | templateUrl: ${{ needs.Initialize.outputs.TemplateUrl }} 144 | directCommit: ${{ env.directCommit }} 145 | updateBranch: ${{ matrix.branch }} 146 | 147 | - name: Finalize the workflow 148 | if: always() 149 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v7.1 150 | env: 151 | GITHUB_TOKEN: ${{ github.token }} 152 | with: 153 | shell: powershell 154 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 155 | currentJobContext: ${{ toJson(job) }} 156 | -------------------------------------------------------------------------------- /.github/workflows/_BuildALGoProject.yaml: -------------------------------------------------------------------------------- 1 | name: '_Build AL-Go project' 2 | 3 | run-name: 'Build ${{ inputs.project }}' 4 | 5 | on: 6 | workflow_call: 7 | inputs: 8 | shell: 9 | description: Shell in which you want to run the action (powershell or pwsh) 10 | required: false 11 | default: powershell 12 | type: string 13 | runsOn: 14 | description: JSON-formatted string of the types of machine to run the build job on 15 | required: true 16 | type: string 17 | checkoutRef: 18 | description: Ref to checkout 19 | required: false 20 | default: ${{ github.sha }} 21 | type: string 22 | project: 23 | description: Name of the built project 24 | required: true 25 | type: string 26 | projectName: 27 | description: Friendly name of the built project 28 | required: true 29 | type: string 30 | skippedProjectsJson: 31 | description: An array of AL-Go projects to skip in compressed JSON format 32 | required: false 33 | default: '[]' 34 | type: string 35 | projectDependenciesJson: 36 | description: Dependencies of the built project in compressed Json format 37 | required: false 38 | default: '{}' 39 | type: string 40 | buildMode: 41 | description: Build mode used when building the artifacts 42 | required: true 43 | type: string 44 | baselineWorkflowRunId: 45 | description: ID of the baseline workflow run, from where to download the current project dependencies, in case they are not built in the current workflow run 46 | required: false 47 | default: '0' 48 | type: string 49 | baselineWorkflowSHA: 50 | description: SHA of the baseline workflow run 51 | required: false 52 | default: '' 53 | type: string 54 | secrets: 55 | description: A comma-separated string with the names of the secrets, required for the workflow. 56 | required: false 57 | default: '' 58 | type: string 59 | artifactsRetentionDays: 60 | description: Number of days to keep the artifacts 61 | type: number 62 | default: 0 63 | artifactsNameSuffix: 64 | description: Suffix to add to the artifacts names 65 | required: false 66 | default: '' 67 | type: string 68 | signArtifacts: 69 | description: Flag indicating whether the apps should be signed 70 | type: boolean 71 | default: false 72 | useArtifactCache: 73 | description: Flag determining whether to use the Artifacts Cache 74 | type: boolean 75 | default: false 76 | 77 | permissions: 78 | actions: read 79 | contents: read 80 | id-token: write 81 | 82 | env: 83 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 84 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 85 | 86 | jobs: 87 | BuildALGoProject: 88 | needs: [ ] 89 | runs-on: ${{ fromJson(inputs.runsOn) }} 90 | defaults: 91 | run: 92 | shell: ${{ inputs.shell }} 93 | name: ${{ inputs.projectName }} (${{ inputs.buildMode }}) 94 | steps: 95 | - name: Checkout 96 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 97 | with: 98 | ref: ${{ inputs.checkoutRef }} 99 | lfs: true 100 | 101 | - name: Read settings 102 | uses: microsoft/AL-Go-Actions/ReadSettings@v7.1 103 | with: 104 | shell: ${{ inputs.shell }} 105 | project: ${{ inputs.project }} 106 | buildMode: ${{ inputs.buildMode }} 107 | get: useCompilerFolder,keyVaultCodesignCertificateName,doNotSignApps,doNotRunTests,doNotRunBcptTests,doNotRunpageScriptingTests,artifact,generateDependencyArtifact,trustedSigning,useGitSubmodules 108 | 109 | - name: Determine whether to build project 110 | id: DetermineBuildProject 111 | uses: microsoft/AL-Go-Actions/DetermineBuildProject@v7.1 112 | with: 113 | shell: ${{ inputs.shell }} 114 | skippedProjectsJson: ${{ inputs.skippedProjectsJson }} 115 | project: ${{ inputs.project }} 116 | baselineWorkflowRunId: ${{ inputs.baselineWorkflowRunId }} 117 | 118 | - name: Read secrets 119 | id: ReadSecrets 120 | if: steps.DetermineBuildProject.outputs.BuildIt == 'True' && github.event_name != 'pull_request' 121 | uses: microsoft/AL-Go-Actions/ReadSecrets@v7.1 122 | with: 123 | shell: ${{ inputs.shell }} 124 | gitHubSecrets: ${{ toJson(secrets) }} 125 | getSecrets: '${{ inputs.secrets }},appDependencySecrets,AZURE_CREDENTIALS,-gitSubmodulesToken' 126 | 127 | - name: Checkout Submodules 128 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 129 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 130 | with: 131 | ref: ${{ inputs.checkoutRef }} 132 | lfs: true 133 | submodules: ${{ env.useGitSubmodules }} 134 | token: '${{ fromJson(steps.ReadSecrets.outputs.Secrets).gitSubmodulesToken }}' 135 | 136 | - name: Determine ArtifactUrl 137 | id: determineArtifactUrl 138 | if: steps.DetermineBuildProject.outputs.BuildIt == 'True' 139 | uses: microsoft/AL-Go-Actions/DetermineArtifactUrl@v7.1 140 | with: 141 | shell: ${{ inputs.shell }} 142 | project: ${{ inputs.project }} 143 | 144 | - name: Cache Business Central Artifacts 145 | if: steps.DetermineBuildProject.outputs.BuildIt == 'True' && env.useCompilerFolder == 'True' && inputs.useArtifactCache && env.artifactCacheKey 146 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 147 | with: 148 | path: ${{ runner.temp }}/.artifactcache 149 | key: ${{ env.artifactCacheKey }} 150 | 151 | - name: Download Project Dependencies 152 | id: DownloadProjectDependencies 153 | if: steps.DetermineBuildProject.outputs.BuildIt == 'True' 154 | uses: microsoft/AL-Go-Actions/DownloadProjectDependencies@v7.1 155 | env: 156 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 157 | with: 158 | shell: ${{ inputs.shell }} 159 | project: ${{ inputs.project }} 160 | buildMode: ${{ inputs.buildMode }} 161 | projectDependenciesJson: ${{ inputs.projectDependenciesJson }} 162 | baselineWorkflowRunId: ${{ inputs.baselineWorkflowRunId }} 163 | 164 | - name: Build 165 | uses: microsoft/AL-Go-Actions/RunPipeline@v7.1 166 | if: steps.DetermineBuildProject.outputs.BuildIt == 'True' 167 | env: 168 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 169 | BuildMode: ${{ inputs.buildMode }} 170 | with: 171 | shell: ${{ inputs.shell }} 172 | artifact: ${{ env.artifact }} 173 | project: ${{ inputs.project }} 174 | buildMode: ${{ inputs.buildMode }} 175 | installAppsJson: ${{ steps.DownloadProjectDependencies.outputs.DownloadedApps }} 176 | installTestAppsJson: ${{ steps.DownloadProjectDependencies.outputs.DownloadedTestApps }} 177 | baselineWorkflowRunId: ${{ inputs.baselineWorkflowRunId }} 178 | baselineWorkflowSHA: ${{ inputs.baselineWorkflowSHA }} 179 | 180 | - name: Sign 181 | id: sign 182 | if: steps.DetermineBuildProject.outputs.BuildIt == 'True' && inputs.signArtifacts && env.doNotSignApps == 'False' && (env.keyVaultCodesignCertificateName != '' || (fromJson(env.trustedSigning).Endpoint != '' && fromJson(env.trustedSigning).Account != '' && fromJson(env.trustedSigning).CertificateProfile != '')) 183 | uses: microsoft/AL-Go-Actions/Sign@v7.1 184 | with: 185 | shell: ${{ inputs.shell }} 186 | azureCredentialsJson: '${{ fromJson(steps.ReadSecrets.outputs.Secrets).AZURE_CREDENTIALS }}' 187 | pathToFiles: '${{ inputs.project }}/.buildartifacts/Apps/*.app' 188 | 189 | - name: Calculate Artifact names 190 | id: calculateArtifactsNames 191 | uses: microsoft/AL-Go-Actions/CalculateArtifactNames@v7.1 192 | if: success() || failure() 193 | with: 194 | shell: ${{ inputs.shell }} 195 | project: ${{ inputs.project }} 196 | buildMode: ${{ inputs.buildMode }} 197 | suffix: ${{ inputs.artifactsNameSuffix }} 198 | 199 | - name: Publish artifacts - apps 200 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 201 | if: inputs.artifactsRetentionDays >= 0 && (hashFiles(format('{0}/.buildartifacts/Apps/*',inputs.project)) != '') 202 | with: 203 | name: ${{ steps.calculateArtifactsNames.outputs.AppsArtifactsName }} 204 | path: '${{ inputs.project }}/.buildartifacts/Apps/' 205 | if-no-files-found: ignore 206 | retention-days: ${{ inputs.artifactsRetentionDays }} 207 | 208 | - name: Publish artifacts - dependencies 209 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 210 | if: inputs.artifactsRetentionDays >= 0 && env.generateDependencyArtifact == 'True' && (hashFiles(format('{0}/.buildartifacts/Dependencies/*',inputs.project)) != '') 211 | with: 212 | name: ${{ steps.calculateArtifactsNames.outputs.DependenciesArtifactsName }} 213 | path: '${{ inputs.project }}/.buildartifacts/Dependencies/' 214 | if-no-files-found: ignore 215 | retention-days: ${{ inputs.artifactsRetentionDays }} 216 | 217 | - name: Publish artifacts - test apps 218 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 219 | if: inputs.artifactsRetentionDays >= 0 && (hashFiles(format('{0}/.buildartifacts/TestApps/*',inputs.project)) != '') 220 | with: 221 | name: ${{ steps.calculateArtifactsNames.outputs.TestAppsArtifactsName }} 222 | path: '${{ inputs.project }}/.buildartifacts/TestApps/' 223 | if-no-files-found: ignore 224 | retention-days: ${{ inputs.artifactsRetentionDays }} 225 | 226 | - name: Publish artifacts - build output 227 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 228 | if: (success() || failure()) && (hashFiles(format('{0}/BuildOutput.txt',inputs.project)) != '') 229 | with: 230 | name: ${{ steps.calculateArtifactsNames.outputs.BuildOutputArtifactsName }} 231 | path: '${{ inputs.project }}/BuildOutput.txt' 232 | if-no-files-found: ignore 233 | 234 | - name: Publish artifacts - container event log 235 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 236 | if: (failure()) && (hashFiles(format('{0}/ContainerEventLog.evtx',inputs.project)) != '') 237 | with: 238 | name: ${{ steps.calculateArtifactsNames.outputs.ContainerEventLogArtifactsName }} 239 | path: '${{ inputs.project }}/ContainerEventLog.evtx' 240 | if-no-files-found: ignore 241 | 242 | - name: Publish artifacts - test results 243 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 244 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/TestResults.xml',inputs.project)) != '') 245 | with: 246 | name: ${{ steps.calculateArtifactsNames.outputs.TestResultsArtifactsName }} 247 | path: '${{ inputs.project }}/.buildartifacts/TestResults.xml' 248 | if-no-files-found: ignore 249 | 250 | - name: Publish artifacts - bcpt test results 251 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 252 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/bcptTestResults.json',inputs.project)) != '') 253 | with: 254 | name: ${{ steps.calculateArtifactsNames.outputs.BcptTestResultsArtifactsName }} 255 | path: '${{ inputs.project }}/.buildartifacts/bcptTestResults.json' 256 | if-no-files-found: ignore 257 | 258 | - name: Publish artifacts - page scripting test results 259 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 260 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/PageScriptingTestResults.xml',inputs.project)) != '') 261 | with: 262 | name: ${{ steps.calculateArtifactsNames.outputs.PageScriptingTestResultsArtifactsName }} 263 | path: '${{ inputs.project }}/.buildartifacts/PageScriptingTestResults.xml' 264 | if-no-files-found: ignore 265 | 266 | - name: Publish artifacts - page scripting test result details 267 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 268 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/PageScriptingTestResultDetails/*',inputs.project)) != '') 269 | with: 270 | name: ${{ steps.calculateArtifactsNames.outputs.PageScriptingTestResultDetailsArtifactsName }} 271 | path: '${{ inputs.project }}/.buildartifacts/PageScriptingTestResultDetails/' 272 | if-no-files-found: ignore 273 | 274 | - name: Analyze Test Results 275 | id: analyzeTestResults 276 | if: (success() || failure()) && env.doNotRunTests == 'False' && ((hashFiles(format('{0}/.buildartifacts/TestResults.xml',inputs.project)) != '') || (hashFiles(format('{0}/.buildartifacts/bcptTestResults.json',inputs.project)) != '')) 277 | uses: microsoft/AL-Go-Actions/AnalyzeTests@v7.1 278 | with: 279 | shell: ${{ inputs.shell }} 280 | project: ${{ inputs.project }} 281 | testType: "normal" 282 | 283 | - name: Analyze BCPT Test Results 284 | id: analyzeTestResultsBCPT 285 | if: (success() || failure()) && env.doNotRunBcptTests == 'False' 286 | uses: microsoft/AL-Go-Actions/AnalyzeTests@v7.1 287 | with: 288 | shell: ${{ inputs.shell }} 289 | project: ${{ inputs.project }} 290 | testType: "bcpt" 291 | 292 | - name: Analyze Page Scripting Test Results 293 | id: analyzeTestResultsPageScripting 294 | if: (success() || failure()) && env.doNotRunpageScriptingTests == 'False' 295 | uses: microsoft/AL-Go-Actions/AnalyzeTests@v7.1 296 | with: 297 | shell: ${{ inputs.shell }} 298 | project: ${{ inputs.project }} 299 | testType: "pageScripting" 300 | 301 | - name: Cleanup 302 | if: always() && steps.DetermineBuildProject.outputs.BuildIt == 'True' 303 | uses: microsoft/AL-Go-Actions/PipelineCleanup@v7.1 304 | with: 305 | shell: ${{ inputs.shell }} 306 | project: ${{ inputs.project }} 307 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.app 2 | *.flf 3 | *.bclicense 4 | *.g.xlf 5 | .DS_Store 6 | Thumbs.db 7 | TestResults*.xml 8 | bcptTestResults*.json 9 | BuildOutput.txt 10 | rad.json 11 | .output/ 12 | .dependencies/ 13 | .buildartifacts/ 14 | .alpackages/ 15 | .packages/ 16 | .alcache/ 17 | .altemplates/ 18 | .snapshots/ 19 | cache_* 20 | ~$* 21 | -------------------------------------------------------------------------------- /App/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Microsoft cloud sandbox", 6 | "request": "launch", 7 | "type": "al", 8 | "environmentType": "Sandbox", 9 | "environmentName": "SandboxV23", 10 | "startupObjectId": 22, 11 | "startupObjectType": "Page", 12 | "breakOnError": "All", 13 | "launchBrowser": true, 14 | "enableLongRunningSqlStatements": true, 15 | "enableSqlInformationDebugger": true, 16 | "schemaUpdateMode": "ForceSync" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /App/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "al.codeAnalyzers": ["${CodeCop}"], 3 | "al.enableCodeAnalysis": true, 4 | "al.compilationOptions": { 5 | "generateReportLayout": true 6 | } 7 | } -------------------------------------------------------------------------------- /App/BioDiversityPlant.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/App/BioDiversityPlant.xlsx -------------------------------------------------------------------------------- /App/BioSample.PermissionSet.al: -------------------------------------------------------------------------------- 1 | permissionset 70074170 BioSample 2 | { 3 | Access = Public; 4 | Assignable = true; 5 | Caption = 'Bio Sample App'; 6 | Permissions = 7 | tabledata MS_BioDiversityMgmtPlant = RIMD, 8 | tabledata MS_BioDiversityMgmtInsect = RIMD; 9 | } 10 | -------------------------------------------------------------------------------- /App/MSAssistedSetupGroup.EnumExt.al: -------------------------------------------------------------------------------- 1 | enumextension 70074173 MS_AssistedSetupGroup extends "Assisted Setup Group" 2 | { 3 | value(70074173; MS_BioDiversity) 4 | { 5 | Caption = 'Bio Diversity Management'; 6 | } 7 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmt.EnumExt.al: -------------------------------------------------------------------------------- 1 | //Your app needs to define a "sign-up context" name. You need to add this to the sign-up URL, along with the profiler answers. 2 | //Make this something that identifies your app (but not the ID). It could include your publisher and app names. Try to make it as unique as possible. 3 | //The sign-up context is useful if other apps want to align their experience to the context. 4 | 5 | enumextension 70074171 MS_BioDiversityMgmt extends "Signup Context" 6 | { 7 | value(70074171; MS_BioDiversityMgmt) 8 | { 9 | Caption = 'Bio Diversity Mgmt.'; 10 | } 11 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmt.PermissionSet.al: -------------------------------------------------------------------------------- 1 | permissionset 70074171 MS_BioDiversityMgmt 2 | { 3 | Assignable = true; 4 | Permissions = codeunit MS_CreateWelcomeExperience = X; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtInsect.Table.al: -------------------------------------------------------------------------------- 1 | table 70074171 MS_BioDiversityMgmtInsect 2 | { 3 | Caption = 'Bio Diversity Insect'; 4 | DataPerCompany = true; 5 | 6 | fields 7 | { 8 | field(1; PrimaryKey; Code[20]) 9 | { 10 | Description = 'Primary key of the table'; 11 | DataClassification = SystemMetadata; 12 | } 13 | field(2; Enabled; Boolean) 14 | { 15 | Description = 'Specifies if the Shoe Management solution is enabled'; 16 | DataClassification = SystemMetadata; 17 | } 18 | } 19 | keys 20 | { 21 | key(PrimaryKey; PrimaryKey) 22 | { 23 | Clustered = TRUE; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtInsectGuide.Page.al: -------------------------------------------------------------------------------- 1 | page 70074170 MS_BioDiversityMgmtInsectGuide 2 | { 3 | Caption = 'Define the list of insects'; 4 | PageType = NavigatePage; 5 | SourceTable = MS_BioDiversityMgmtInsect; 6 | SourceTableTemporary = true; 7 | 8 | layout 9 | { 10 | area(content) 11 | { 12 | group(StandardBanner) 13 | { 14 | Caption = ''; 15 | Editable = false; 16 | Visible = TopBannerVisible and not FinishActionEnabled; 17 | field(MediaResourcesStandard; MediaResourcesStandard."Media Reference") 18 | { 19 | ApplicationArea = All; 20 | Editable = false; 21 | ShowCaption = false; 22 | } 23 | } 24 | group(FinishedBanner) 25 | { 26 | Caption = ''; 27 | Editable = false; 28 | Visible = TopBannerVisible and FinishActionEnabled; 29 | field(MediaResourcesDone; MediaResourcesDone."Media Reference") 30 | { 31 | ApplicationArea = All; 32 | Editable = false; 33 | ShowCaption = false; 34 | } 35 | } 36 | 37 | group(Step1) 38 | { 39 | Visible = Step1Visible; 40 | group("Welcome to PageName") 41 | { 42 | Caption = 'Welcome to Shoe Management Setup'; 43 | Visible = Step1Visible; 44 | group(Group18) 45 | { 46 | Caption = ''; 47 | InstructionalText = 'Step1 - Replace this text with some instructions.'; 48 | } 49 | } 50 | group("Let's go!") 51 | { 52 | Caption = 'Let''s go!'; 53 | group(Group22) 54 | { 55 | Caption = ''; 56 | InstructionalText = 'Step1 - Replace this text with some more instructions.'; 57 | } 58 | } 59 | } 60 | 61 | group(Step2) 62 | { 63 | Caption = ''; 64 | InstructionalText = 'Step2 - Replace this text with some instructions.'; 65 | Visible = Step2Visible; 66 | //You might want to add fields here 67 | } 68 | 69 | 70 | group(Step3) 71 | { 72 | Visible = Step3Visible; 73 | group(Group23) 74 | { 75 | Caption = ''; 76 | InstructionalText = 'Step3 - Replace this text with some instructions.'; 77 | } 78 | group("That's it!") 79 | { 80 | Caption = 'That''s it!'; 81 | group(Group25) 82 | { 83 | Caption = ''; 84 | InstructionalText = 'To save this setup, choose Finish.'; 85 | } 86 | } 87 | } 88 | } 89 | } 90 | actions 91 | { 92 | area(processing) 93 | { 94 | action(ActionBack) 95 | { 96 | ApplicationArea = All; 97 | Caption = 'Back'; 98 | Enabled = BackActionEnabled; 99 | Image = PreviousRecord; 100 | InFooterBar = true; 101 | trigger OnAction(); 102 | begin 103 | NextStep(true); 104 | end; 105 | } 106 | action(ActionNext) 107 | { 108 | ApplicationArea = All; 109 | Caption = 'Next'; 110 | Enabled = NextActionEnabled; 111 | Image = NextRecord; 112 | InFooterBar = true; 113 | trigger OnAction(); 114 | begin 115 | NextStep(false); 116 | end; 117 | } 118 | action(ActionFinish) 119 | { 120 | ApplicationArea = All; 121 | Caption = 'Finish'; 122 | Enabled = FinishActionEnabled; 123 | Image = Approve; 124 | InFooterBar = true; 125 | trigger OnAction(); 126 | begin 127 | FinishAction(); 128 | end; 129 | } 130 | } 131 | } 132 | 133 | trigger OnInit(); 134 | begin 135 | LoadTopBanners(); 136 | end; 137 | 138 | trigger OnOpenPage(); 139 | var 140 | begin 141 | 142 | Step := Step::Start; 143 | EnableControls(); 144 | end; 145 | 146 | var 147 | MediaRepositoryDone: Record "Media Repository"; 148 | MediaRepositoryStandard: Record "Media Repository"; 149 | MediaResourcesDone: Record "Media Resources"; 150 | MediaResourcesStandard: Record "Media Resources"; 151 | Step: Option Start,Step2,Finish; 152 | BackActionEnabled: Boolean; 153 | FinishActionEnabled: Boolean; 154 | NextActionEnabled: Boolean; 155 | Step1Visible: Boolean; 156 | Step2Visible: Boolean; 157 | Step3Visible: Boolean; 158 | TopBannerVisible: Boolean; 159 | 160 | local procedure EnableControls(); 161 | begin 162 | ResetControls(); 163 | 164 | case Step of 165 | Step::Start: 166 | ShowStep1(); 167 | Step::Step2: 168 | ShowStep2(); 169 | Step::Finish: 170 | ShowStep3(); 171 | end; 172 | end; 173 | 174 | local procedure StoreRecordVar(); 175 | var 176 | //PlantsRec: Record MS_BioDiversityMgmtPlant; 177 | begin 178 | 179 | end; 180 | 181 | local procedure FinishAction(); 182 | begin 183 | StoreRecordVar(); 184 | CurrPage.Close(); 185 | end; 186 | 187 | local procedure NextStep(Backwards: Boolean); 188 | begin 189 | if Backwards then 190 | Step := Step - 1 191 | else 192 | Step := Step + 1; 193 | 194 | EnableControls(); 195 | end; 196 | 197 | local procedure ShowStep1(); 198 | begin 199 | Step1Visible := true; 200 | 201 | FinishActionEnabled := false; 202 | BackActionEnabled := false; 203 | end; 204 | 205 | local procedure ShowStep2(); 206 | begin 207 | Step2Visible := true; 208 | end; 209 | 210 | local procedure ShowStep3(); 211 | begin 212 | Step3Visible := true; 213 | 214 | NextActionEnabled := false; 215 | FinishActionEnabled := true; 216 | end; 217 | 218 | local procedure ResetControls(); 219 | begin 220 | FinishActionEnabled := false; 221 | BackActionEnabled := true; 222 | NextActionEnabled := true; 223 | 224 | Step1Visible := false; 225 | Step2Visible := false; 226 | Step3Visible := false; 227 | end; 228 | 229 | local procedure LoadTopBanners(); 230 | begin 231 | if MediaRepositoryStandard.Get('AssistedSetup-NoText-400px.png', Format(CurrentClientType())) and 232 | MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', Format(CurrentClientType())) 233 | then 234 | if MediaResourcesStandard.Get(MediaRepositoryStandard."Media Resources Ref") and 235 | MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref") 236 | then 237 | TopBannerVisible := MediaResourcesDone."Media Reference".HasValue(); 238 | end; 239 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtInsects.Page.al: -------------------------------------------------------------------------------- 1 | page 70074172 MS_BioDiversityMgmtInsects 2 | { 3 | PageType = List; 4 | ApplicationArea = All; 5 | SourceTable = MS_BioDiversityMgmtInsect; 6 | UsageCategory = Lists; 7 | Caption = 'Insects'; 8 | 9 | layout 10 | { 11 | area(Content) 12 | { 13 | repeater(Group) 14 | { 15 | field(PrimaryKey; Rec.PrimaryKey) 16 | { 17 | ApplicationArea = All; 18 | ToolTip = 'Specifies a unique identifier of the Insect'; 19 | Caption = 'Plant Code'; 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtLocalTest.Codeuit.al: -------------------------------------------------------------------------------- 1 | codeunit 70074171 MS_BioDiversityMgmtLocalTest 2 | { 3 | Subtype = Install; 4 | 5 | trigger OnInstallAppPerCompany() 6 | var 7 | MSCreateWelcomeExperience: Codeunit MS_CreateWelcomeExperience; 8 | begin 9 | MSCreateWelcomeExperience.AddGuidedExperienceItems(); 10 | MSCreateWelcomeExperience.FakeTestsWhenNotInSignup(); 11 | MSCreateWelcomeExperience.SetCurrentUserRole(); 12 | end; 13 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPlant.Table.al: -------------------------------------------------------------------------------- 1 | table 70074170 MS_BioDiversityMgmtPlant 2 | { 3 | Caption = 'Bio Diversity Plant'; 4 | DataPerCompany = true; 5 | 6 | fields 7 | { 8 | field(1; PlantCode; Code[30]) 9 | { 10 | Description = 'This code specifies a unique identifier of the plant'; 11 | DataClassification = SystemMetadata; 12 | } 13 | field(2; "Name"; text[100]) 14 | { 15 | Description = 'Specifies if name of the plant'; 16 | DataClassification = SystemMetadata; 17 | } 18 | field(3; "Description"; text[1000]) 19 | { 20 | Description = 'Specifies if description of the plant'; 21 | DataClassification = SystemMetadata; 22 | } 23 | field(4; IsPollinator; Boolean) 24 | { 25 | Description = 'Specifies if this plant acts as a pollinator for other plants'; 26 | DataClassification = SystemMetadata; 27 | } 28 | field(5; PollinatedBy; Enum MS_BioDiversityMgmtPollinator) 29 | { 30 | Description = 'Specifies how the plant is pollinated'; 31 | DataClassification = SystemMetadata; 32 | } 33 | field(6; Occurrences; Integer) 34 | { 35 | Description = 'Specifies how often the plant has been reported spotted in nature the last year.'; 36 | DataClassification = SystemMetadata; 37 | } 38 | field(7; Family; Code[50]) 39 | { 40 | TableRelation = MS_BioDiversityMgmtPlantFamily; 41 | Description = 'Specifies the family of plants to which this plant belongs.'; 42 | DataClassification = SystemMetadata; 43 | } 44 | } 45 | keys 46 | { 47 | key(PrimaryKey; PlantCode) 48 | { 49 | Clustered = TRUE; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPlantFamilies.Page.al: -------------------------------------------------------------------------------- 1 | page 70074174 MS_BioDivMgmtPlantFamilies 2 | { 3 | PageType = List; 4 | ApplicationArea = All; 5 | SourceTable = MS_BioDiversityMgmtPlantFamily; 6 | UsageCategory = Lists; 7 | Caption = 'Plant Families'; 8 | AboutTitle = 'Plant families'; 9 | AboutText = 'Here you create the plant families your plants belong to.'; 10 | 11 | layout 12 | { 13 | area(Content) 14 | { 15 | repeater(Group) 16 | { 17 | field(PlantCode; Rec.FamilyCode) 18 | { 19 | ApplicationArea = All; 20 | ToolTip = 'Specifies a unique identifier of the plant family'; 21 | Caption = 'Family Code'; 22 | } 23 | field(Name; Rec.Name) 24 | { 25 | ApplicationArea = All; 26 | ToolTip = 'Specifies a name of the plant family'; 27 | Caption = 'Name'; 28 | } 29 | field(Description; Rec.Description) 30 | { 31 | ApplicationArea = All; 32 | ToolTip = 'Specifies a description of the plant family'; 33 | Caption = 'Description'; 34 | } 35 | field(Characteristics; Rec.Characteristics) 36 | { 37 | ApplicationArea = All; 38 | ToolTip = 'Specifies characteristics of the plant family'; 39 | Caption = 'Characteristics'; 40 | } 41 | } 42 | } 43 | } 44 | actions 45 | { 46 | area(Reporting) 47 | { 48 | action("Top Plants") 49 | { 50 | Image = AnalysisView; 51 | ApplicationArea = All; 52 | RunObject = query MS_BioDiversityMgmtPlants; 53 | Tooltip = 'Open the Plants query in analysis mode.'; 54 | AboutTitle = 'Analyse top plants'; 55 | AboutText = 'Here you can analyse and pivot on plant data, to get a sense of the progress you are making on plants. There is a similar analysis option available If you are looking for [Insects](?page=70074172 "Opens the Insects page").'; 56 | 57 | trigger OnAction(); 58 | begin 59 | 60 | end; 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPlantFamily.Table.al: -------------------------------------------------------------------------------- 1 | table 70074172 MS_BioDiversityMgmtPlantFamily 2 | { 3 | Caption = 'Bio Diversity Plant Family'; 4 | DataPerCompany = true; 5 | LookupPageId = 70074174; 6 | 7 | fields 8 | { 9 | field(1; FamilyCode; Code[50]) 10 | { 11 | Description = 'This code specifies a unique identifier of the plant family'; 12 | DataClassification = SystemMetadata; 13 | } 14 | field(2; "Name"; text[100]) 15 | { 16 | Description = 'Specifies the name of the plant family'; 17 | DataClassification = SystemMetadata; 18 | } 19 | field(3; "Description"; text[1000]) 20 | { 21 | Description = 'Specifies the description of the plant family'; 22 | DataClassification = SystemMetadata; 23 | } 24 | field(4; "Characteristics"; text[100]) 25 | { 26 | Description = 'Specifies the description of the plant family'; 27 | DataClassification = SystemMetadata; 28 | } 29 | } 30 | keys 31 | { 32 | key(PrimaryKey; FamilyCode) 33 | { 34 | Clustered = TRUE; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPlantGuide.Page.al: -------------------------------------------------------------------------------- 1 | page 70074176 MS_BioDiversityMgmtPlantGuide 2 | { 3 | Caption = 'Define the list of plants'; 4 | PageType = NavigatePage; 5 | SourceTable = MS_BioDiversityMgmtPlant; 6 | SourceTableTemporary = true; 7 | ApplicationArea = All; 8 | Permissions = tabledata MS_BioDiversityMgmtPlant = ri; 9 | 10 | layout 11 | { 12 | area(content) 13 | { 14 | group(CustomBanner) 15 | { 16 | Caption = ''; 17 | Editable = false; 18 | Visible = CustomBannerVisible; 19 | 20 | field(BioDiversitySetup; BioDiversitySetup.SetupWizardBanner) 21 | { 22 | ApplicationArea = All; 23 | Editable = false; 24 | MultiLine = true; 25 | ShowCaption = false; 26 | } 27 | } 28 | 29 | group(FinishedBanner) 30 | { 31 | Caption = ''; 32 | Editable = false; 33 | Visible = TopBannerVisible and FinishActionEnabled; 34 | field(MediaResourcesDone; MediaResourcesDone."Media Reference") 35 | { 36 | ApplicationArea = All; 37 | Editable = false; 38 | ShowCaption = false; 39 | } 40 | } 41 | 42 | group(Step1) 43 | { 44 | Visible = Step1Visible; 45 | 46 | group("Welcome to PageName") 47 | { 48 | Caption = 'Welcome to Bio Diversity Management Setup'; 49 | Visible = Step1Visible; 50 | 51 | group(Group18) 52 | { 53 | Caption = ''; 54 | InstructionalText = 'Step1 - Import the list of plants.'; 55 | } 56 | } 57 | group("Let's go!") 58 | { 59 | Caption = 'Let''s go!'; 60 | group(Group22) 61 | { 62 | Caption = ''; 63 | InstructionalText = 'When you click next we will import a list from Github of well known plants. You will get the chance to review the list before we store it in your system.'; 64 | } 65 | } 66 | } 67 | 68 | group(Step2) 69 | { 70 | Caption = ''; 71 | InstructionalText = 'Step2 - Verify the list of plants.'; 72 | Visible = Step2Visible; 73 | Editable = false; 74 | //You might want to add fields here 75 | group(Group24) 76 | { 77 | Caption = ''; 78 | InstructionalText = 'Please verify that the list looks like you expect it. When you click next, we will store the list of plants your system. You can find it in the Plants page.'; 79 | } 80 | repeater(TempPlants) 81 | { 82 | field("Plant Name"; Rec.Name) 83 | { 84 | ToolTip = 'Name of the plant'; 85 | } 86 | 87 | field("Family"; Rec.Family) 88 | { 89 | ToolTip = 'Family of the plant'; 90 | } 91 | 92 | field("Plant Description"; Rec.Description) 93 | { 94 | ToolTip = 'Description of the plant'; 95 | } 96 | } 97 | } 98 | 99 | group(Step3) 100 | { 101 | Visible = Step3Visible; 102 | group(Group23) 103 | { 104 | Caption = ''; 105 | InstructionalText = 'Congratulations! We are done with importing plants.'; 106 | } 107 | group("That's it!") 108 | { 109 | Caption = 'That''s it!'; 110 | group(Group25) 111 | { 112 | Caption = ''; 113 | InstructionalText = 'To close this setup, choose Finish.'; 114 | } 115 | } 116 | } 117 | } 118 | } 119 | actions 120 | { 121 | area(processing) 122 | { 123 | action(ActionBack) 124 | { 125 | ApplicationArea = All; 126 | Caption = 'Back'; 127 | Enabled = BackActionEnabled; 128 | Image = PreviousRecord; 129 | InFooterBar = true; 130 | trigger OnAction(); 131 | begin 132 | NextStep(true); 133 | end; 134 | } 135 | action(ActionNext) 136 | { 137 | ApplicationArea = All; 138 | Caption = 'Next'; 139 | Enabled = NextActionEnabled; 140 | Image = NextRecord; 141 | InFooterBar = true; 142 | trigger OnAction(); 143 | begin 144 | NextStep(false); 145 | end; 146 | } 147 | action(ActionFinish) 148 | { 149 | ApplicationArea = All; 150 | Caption = 'Finish'; 151 | Enabled = FinishActionEnabled; 152 | Image = Approve; 153 | InFooterBar = true; 154 | trigger OnAction(); 155 | begin 156 | FinishAction(); 157 | end; 158 | } 159 | } 160 | } 161 | 162 | trigger OnInit(); 163 | begin 164 | LoadCustomBanner(); 165 | LoadTopBanners(); 166 | end; 167 | 168 | trigger OnOpenPage(); 169 | var 170 | begin 171 | Step := Step::Start; 172 | EnableControls(); 173 | end; 174 | 175 | var 176 | MediaRepositoryDone: Record "Media Repository"; 177 | MediaRepositoryStandard: Record "Media Repository"; 178 | MediaResourcesDone: Record "Media Resources"; 179 | MediaResourcesStandard: Record "Media Resources"; 180 | BioDiversitySetup: Record MS_BioDiversityMgmtSetup; 181 | 182 | Step: Option Start,Step2,Finish; 183 | BackActionEnabled: Boolean; 184 | FinishActionEnabled: Boolean; 185 | NextActionEnabled: Boolean; 186 | Step1Visible: Boolean; 187 | Step2Visible: Boolean; 188 | Step3Visible: Boolean; 189 | TopBannerVisible: Boolean; 190 | CustomBannerVisible: Boolean; 191 | 192 | local procedure EnableControls(); 193 | begin 194 | ResetControls(); 195 | 196 | case Step of 197 | Step::Start: 198 | ShowStep1(); 199 | Step::Step2: 200 | ShowStep2(); 201 | Step::Finish: 202 | ShowStep3(); 203 | end; 204 | end; 205 | 206 | local procedure FinishAction(); 207 | begin 208 | CurrPage.Close(); 209 | end; 210 | 211 | local procedure NextStep(Backwards: Boolean); 212 | begin 213 | if Backwards then 214 | Step := Step - 1 215 | else 216 | Step := Step + 1; 217 | 218 | EnableControls(); 219 | end; 220 | 221 | local procedure ShowStep1(); 222 | begin 223 | Step1Visible := true; 224 | 225 | FinishActionEnabled := false; 226 | BackActionEnabled := false; 227 | end; 228 | 229 | local procedure ShowStep2(); 230 | var 231 | Plants: JsonToken; 232 | begin 233 | Step2Visible := true; 234 | 235 | if not Rec.IsEmpty() then 236 | exit; 237 | 238 | Plants := LoadPlantsFromGitHub(); 239 | LoadJsonResponseToTempTable(Plants); 240 | end; 241 | 242 | local procedure ShowStep3(); 243 | begin 244 | FlushRecordsIntoDB(); 245 | Step3Visible := true; 246 | 247 | NextActionEnabled := false; 248 | FinishActionEnabled := true; 249 | end; 250 | 251 | local procedure ResetControls(); 252 | begin 253 | FinishActionEnabled := false; 254 | BackActionEnabled := true; 255 | NextActionEnabled := true; 256 | 257 | Step1Visible := false; 258 | Step2Visible := false; 259 | Step3Visible := false; 260 | end; 261 | 262 | local procedure LoadTopBanners(); 263 | begin 264 | if MediaRepositoryStandard.Get('AssistedSetup-NoText-400px.png', Format(CurrentClientType())) and 265 | MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', Format(CurrentClientType())) 266 | then 267 | if MediaResourcesStandard.Get(MediaRepositoryStandard."Media Resources Ref") and 268 | MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref") 269 | then 270 | TopBannerVisible := MediaResourcesDone."Media Reference".HasValue(); 271 | end; 272 | 273 | local procedure LoadCustomBanner(); 274 | var 275 | SetupKey: Code[20]; 276 | begin 277 | SetupKey := 'BIODIVSETUP'; 278 | if BioDiversitySetup.Get(SetupKey) then begin 279 | BioDiversitySetup.CalcFields(SetupWizardBanner); 280 | CustomBannerVisible := BioDiversitySetup.SetupWizardBanner.HasValue(); 281 | end; 282 | end; 283 | 284 | local procedure LoadPlantsFromGitHub() Plants: JsonToken 285 | var 286 | HttpClient: HttpClient; 287 | HttpResponseMessage: HttpResponseMessage; 288 | JsonObject: JsonObject; 289 | ResponseContent: Text; 290 | begin 291 | HttpClient.Get('https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/main/App/plants.json', HttpResponseMessage); 292 | 293 | if HttpResponseMessage.IsSuccessStatusCode() then begin 294 | HttpResponseMessage.Content().ReadAs(ResponseContent); 295 | JsonObject.ReadFrom(ResponseContent); 296 | JsonObject.Get('plants', Plants); 297 | end else 298 | Error('Error: Something went wrong while loading the plants from GitHub.'); 299 | end; 300 | 301 | local procedure LoadJsonResponseToTempTable(Plants: JsonToken) 302 | var 303 | PlantFamily: Record MS_BioDiversityMgmtPlantFamily; 304 | Plant, PlantName, PlantDescription, FamilyName, FamilyDescription, FamilyCharacteristics : JsonToken; 305 | begin 306 | foreach Plant in Plants.AsArray() do begin 307 | 308 | //Family first 309 | Plant.AsObject().Get('Family Name', FamilyName); 310 | Plant.AsObject().Get('Family Description', FamilyDescription); 311 | Plant.AsObject().Get('Family Characteristics', FamilyCharacteristics); 312 | 313 | if not PlantFamily.get(Format(FamilyName.AsValue().AsText())) then begin 314 | PlantFamily.Init(); 315 | PlantFamily.FamilyCode := Format(FamilyName.AsValue().AsText()); 316 | PlantFamily.Name := Format(FamilyName.AsValue().AsText()); 317 | PlantFamily.Description := Format(FamilyDescription.AsValue().AsText()); 318 | PlantFamily.Characteristics := Format(FamilyCharacteristics.AsValue().AsText()); 319 | PlantFamily.Insert(); 320 | end; 321 | 322 | 323 | Plant.AsObject().Get('Name', PlantName); 324 | Plant.AsObject().Get('Plant Characteristics', PlantDescription); 325 | 326 | Rec.Init(); 327 | Rec.PlantCode := delchr(PlantName.AsValue().AsText(), '=', ' '); 328 | Rec.Name := CopyStr(PlantName.AsValue().AsText(), 1, 100); 329 | Rec.Description := CopyStr(PlantDescription.AsValue().AsText(), 1, 1000); 330 | Rec.Family := Format(FamilyName.AsValue().AsText()); 331 | if not Rec.Insert() then 332 | rec.Modify(); 333 | end; 334 | end; 335 | 336 | local procedure FlushRecordsIntoDB() 337 | var 338 | Plant: Record MS_BioDiversityMgmtPlant; 339 | begin 340 | if Rec.FindSet() then 341 | repeat 342 | Plant.Init(); 343 | Plant.PlantCode := Rec.PlantCode; 344 | Plant.Name := Rec.Name; 345 | Plant.Description := Rec.Description; 346 | Plant.Family := Rec.Family; 347 | Plant.Occurrences := Random(999); 348 | Plant.Insert(); 349 | until Rec.Next() = 0; 350 | end; 351 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPlants.Page.al: -------------------------------------------------------------------------------- 1 | page 70074171 MS_BioDiversityMgmtPlants 2 | { 3 | PageType = List; 4 | ApplicationArea = All; 5 | SourceTable = MS_BioDiversityMgmtPlant; 6 | UsageCategory = Lists; 7 | Caption = 'Plants'; 8 | AboutTitle = 'Track your plants'; 9 | AboutText = 'Here you can track plants and how often they are spotted in the wild. Also remember to keep track of [Insects](?page=70074171 "Opens the Insects page").'; 10 | 11 | layout 12 | { 13 | area(Content) 14 | { 15 | repeater(Group) 16 | { 17 | field(PlantCode; Rec.PlantCode) 18 | { 19 | ApplicationArea = All; 20 | ToolTip = 'Specifies a unique identifier of the plant'; 21 | Caption = 'Plant Code'; 22 | } 23 | field(Name; Rec.Name) 24 | { 25 | ApplicationArea = All; 26 | ToolTip = 'Specifies a name of the plant'; 27 | Caption = 'Name'; 28 | } 29 | field(Description; Rec.Description) 30 | { 31 | ApplicationArea = All; 32 | ToolTip = 'Specifies a description of the plant'; 33 | Caption = 'Description'; 34 | } 35 | field(Family; Rec.Family) 36 | { 37 | ApplicationArea = All; 38 | ToolTip = 'Specifies the family the plant belongs to'; 39 | Caption = 'Family'; 40 | } 41 | 42 | field(IsPollinator; Rec.IsPollinator) 43 | { 44 | ApplicationArea = All; 45 | ToolTip = 'Specifies if this plant acts as a pollinator of other plants'; 46 | Caption = 'Is Pollinator'; 47 | } 48 | field(PollinatedBy; Rec.PollinatedBy) 49 | { 50 | ApplicationArea = All; 51 | ToolTip = 'Specifies what pollinates this plant.'; 52 | Caption = 'Pollinated By'; 53 | } 54 | field(ReportedOccurencesLastyear; Rec.Occurrences) 55 | { 56 | ApplicationArea = All; 57 | ToolTip = 'Specifies how often this plant was reported spotted in nature last year.'; 58 | Caption = 'Reported Occurrences'; 59 | } 60 | } 61 | } 62 | } 63 | actions 64 | { 65 | area(Reporting) 66 | { 67 | action("Top Plants") 68 | { 69 | Image = AnalysisView; 70 | ApplicationArea = All; 71 | RunObject = query MS_BioDiversityMgmtPlants; 72 | Tooltip = 'Open the Plants query in analysis mode.'; 73 | AboutTitle = 'Analyse top plants'; 74 | AboutText = 'Here you can analyse and pivot on plant data, to get a sense of the progress you are making on plants. There is a similar analysis option available If you are looking for [Insects](?page=70074172 "Opens the Insects page").'; 75 | 76 | trigger OnAction(); 77 | begin 78 | 79 | end; 80 | } 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPlants.Query.al: -------------------------------------------------------------------------------- 1 | query 70074170 MS_BioDiversityMgmtPlants 2 | { 3 | QueryType = Normal; 4 | Caption = 'Top Plants'; 5 | DataAccessIntent = ReadOnly; 6 | QueryCategory = 'Plants'; 7 | OrderBy = descending(Occurrences); 8 | 9 | AboutTitle = 'Analyse Top Plants'; 10 | AboutText = 'Here you see the top plants spotted in the wild. By default the view is sorted by **number of occurrences** in the last year. You can create additional analysis views for more insights. Click around!'; 11 | 12 | elements 13 | { 14 | dataitem(DataItem1; MS_BioDiversityMgmtPlant) 15 | { 16 | 17 | 18 | column(PlantCode; PlantCode) 19 | { 20 | } 21 | column(Name; Name) 22 | { 23 | } 24 | column(Family; Family) 25 | { 26 | } 27 | column(Description; Description) 28 | { 29 | } 30 | column(Occurrences; Occurrences) 31 | { 32 | } 33 | 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtPollinator.Enum.al: -------------------------------------------------------------------------------- 1 | enum 70074170 MS_BioDiversityMgmtPollinator 2 | { 3 | Extensible = true; 4 | 5 | value(0; "Self") 6 | { 7 | Caption = 'Self pollinated'; 8 | } 9 | value(1; "Insect") 10 | { 11 | Caption = 'Insect'; 12 | } 13 | value(2; "Plant") 14 | { 15 | Caption = 'Plant'; 16 | } 17 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtProfile.Profile.al: -------------------------------------------------------------------------------- 1 | profile MS_BioDiversityMgmtProfile 2 | { 3 | Description = 'This profile is used for the Shoe Management user, which we expect is the one signing up to Business Central in this example.'; 4 | Caption = 'Bio Diversity Manager'; 5 | ProfileDescription = 'This profile is for shoe managers, people who start the Business Central trial with the Onboarding Sample App (Shoe Management) installed'; 6 | RoleCenter = MS_BioDiversityMgmtRoleCenter; 7 | Enabled = true; 8 | Promoted = true; 9 | //Customizations = MyCustomization; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtRoleCenter.Page.al: -------------------------------------------------------------------------------- 1 | page 70074178 MS_BioDiversityMgmtRoleCenter 2 | { 3 | PageType = RoleCenter; 4 | Caption = 'Bio Diversity Management Setup'; 5 | 6 | layout 7 | { 8 | area(RoleCenter) 9 | { 10 | 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtSetup.Page.al: -------------------------------------------------------------------------------- 1 | page 70074173 MS_BioDiversityMgmtSetup 2 | { 3 | PageType = Card; 4 | UsageCategory = Administration; 5 | SourceTable = MS_BioDiversityMgmtSetup; 6 | ApplicationArea = All; 7 | Caption = 'Bio Diversity Setup'; 8 | 9 | layout 10 | { 11 | area(Content) 12 | { 13 | group(General) 14 | { 15 | field(Enabled; Rec.Enabled) 16 | { 17 | ToolTip = 'Specifies if the Bio Diversity solution is enabled.'; 18 | ApplicationArea = All; 19 | } 20 | field(SetupWizardBanner; Rec.SetupWizardBanner) 21 | { 22 | ToolTip = 'This is our banner we use in steup wizards.'; 23 | ApplicationArea = All; 24 | 25 | } 26 | } 27 | } 28 | 29 | } 30 | trigger OnAfterGetRecord() 31 | begin 32 | Rec.CalcFields(SetupWizardBanner); 33 | end; 34 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtSetup.Table.al: -------------------------------------------------------------------------------- 1 | table 70074175 MS_BioDiversityMgmtSetup 2 | { 3 | Caption = 'Bio Diversity Management Setup'; 4 | DataPerCompany = true; 5 | InherentEntitlements = RIMDX; 6 | InherentPermissions = RIMDX; 7 | 8 | fields 9 | { 10 | field(1; PrimaryKey; Code[20]) 11 | { 12 | Description = 'Primary key of the table'; 13 | DataClassification = SystemMetadata; 14 | } 15 | field(2; Enabled; Boolean) 16 | { 17 | Description = 'Specifies if the Bio Diversity solution is enabled'; 18 | DataClassification = SystemMetadata; 19 | } 20 | field(3; SetupWizardBanner; Blob) 21 | { 22 | Subtype = Bitmap; 23 | Description = 'Specifies the banner to be used in assisted setups.'; 24 | DataClassification = SystemMetadata; 25 | } 26 | } 27 | keys 28 | { 29 | key(PrimaryKey; PrimaryKey) 30 | { 31 | Clustered = TRUE; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtSetupGuide.Page.al: -------------------------------------------------------------------------------- 1 | page 70074177 MS_BioDiversityMgmtSetupGuide 2 | { 3 | Caption = 'Bio Diversity Management Setup'; 4 | PageType = NavigatePage; 5 | SourceTable = MS_BioDiversityMgmtSetup; 6 | SourceTableTemporary = true; 7 | 8 | layout 9 | { 10 | area(content) 11 | { 12 | group(StandardBanner) 13 | { 14 | Caption = ''; 15 | Editable = false; 16 | Visible = TopBannerVisible and not FinishActionEnabled; 17 | field(MediaResourcesStandard; MediaResourcesStandard."Media Reference") 18 | { 19 | ApplicationArea = All; 20 | Editable = false; 21 | ShowCaption = false; 22 | } 23 | } 24 | group(FinishedBanner) 25 | { 26 | Caption = ''; 27 | Editable = false; 28 | Visible = TopBannerVisible and FinishActionEnabled; 29 | field(MediaResourcesDone; MediaResourcesDone."Media Reference") 30 | { 31 | ApplicationArea = All; 32 | Editable = false; 33 | ShowCaption = false; 34 | } 35 | } 36 | 37 | group(Step1) 38 | { 39 | Visible = Step1Visible; 40 | group("Welcome to PageName") 41 | { 42 | Caption = 'Welcome to Shoe Management Setup'; 43 | Visible = Step1Visible; 44 | group(Group18) 45 | { 46 | Caption = ''; 47 | InstructionalText = 'Step1 - Replace this text with some instructions.'; 48 | } 49 | } 50 | group("Let's go!") 51 | { 52 | Caption = 'Let''s go!'; 53 | group(Group22) 54 | { 55 | Caption = ''; 56 | InstructionalText = 'Step1 - Replace this text with some more instructions.'; 57 | } 58 | } 59 | } 60 | 61 | group(Step2) 62 | { 63 | Caption = ''; 64 | InstructionalText = 'Step2 - Replace this text with some instructions.'; 65 | Visible = Step2Visible; 66 | //You might want to add fields here 67 | } 68 | 69 | 70 | group(Step3) 71 | { 72 | Visible = Step3Visible; 73 | group(Group23) 74 | { 75 | Caption = ''; 76 | InstructionalText = 'Step3 - Replace this text with some instructions.'; 77 | } 78 | group("That's it!") 79 | { 80 | Caption = 'That''s it!'; 81 | group(Group25) 82 | { 83 | Caption = ''; 84 | InstructionalText = 'To save this setup, choose Finish.'; 85 | } 86 | } 87 | } 88 | } 89 | } 90 | actions 91 | { 92 | area(processing) 93 | { 94 | action(ActionBack) 95 | { 96 | ApplicationArea = All; 97 | Caption = 'Back'; 98 | Enabled = BackActionEnabled; 99 | Image = PreviousRecord; 100 | InFooterBar = true; 101 | trigger OnAction(); 102 | begin 103 | NextStep(true); 104 | end; 105 | } 106 | action(ActionNext) 107 | { 108 | ApplicationArea = All; 109 | Caption = 'Next'; 110 | Enabled = NextActionEnabled; 111 | Image = NextRecord; 112 | InFooterBar = true; 113 | trigger OnAction(); 114 | begin 115 | NextStep(false); 116 | end; 117 | } 118 | action(ActionFinish) 119 | { 120 | ApplicationArea = All; 121 | Caption = 'Finish'; 122 | Enabled = FinishActionEnabled; 123 | Image = Approve; 124 | InFooterBar = true; 125 | trigger OnAction(); 126 | begin 127 | FinishAction(); 128 | end; 129 | } 130 | } 131 | } 132 | 133 | trigger OnInit(); 134 | begin 135 | LoadTopBanners(); 136 | end; 137 | 138 | trigger OnOpenPage(); 139 | var 140 | CompanyInformation: Record "Company Information"; 141 | begin 142 | Rec.Init(); 143 | if CompanyInformation.Get() then 144 | Rec.TransferFields(CompanyInformation); 145 | 146 | Rec.Insert(); 147 | 148 | Step := Step::Start; 149 | EnableControls(); 150 | end; 151 | 152 | var 153 | MediaRepositoryDone: Record "Media Repository"; 154 | MediaRepositoryStandard: Record "Media Repository"; 155 | MediaResourcesDone: Record "Media Resources"; 156 | MediaResourcesStandard: Record "Media Resources"; 157 | Step: Option Start,Step2,Finish; 158 | BackActionEnabled: Boolean; 159 | FinishActionEnabled: Boolean; 160 | NextActionEnabled: Boolean; 161 | Step1Visible: Boolean; 162 | Step2Visible: Boolean; 163 | Step3Visible: Boolean; 164 | TopBannerVisible: Boolean; 165 | 166 | local procedure EnableControls(); 167 | begin 168 | ResetControls(); 169 | 170 | case Step of 171 | Step::Start: 172 | ShowStep1(); 173 | Step::Step2: 174 | ShowStep2(); 175 | Step::Finish: 176 | ShowStep3(); 177 | end; 178 | end; 179 | 180 | local procedure StoreRecordVar(); 181 | var 182 | MS_BioDiversityMgmtSetup: Record MS_BioDiversityMgmtSetup; 183 | begin 184 | if not MS_BioDiversityMgmtSetup.Get() then begin 185 | MS_BioDiversityMgmtSetup.Init(); 186 | MS_BioDiversityMgmtSetup.Insert(); 187 | end; 188 | 189 | MS_BioDiversityMgmtSetup.TransferFields(Rec, false); 190 | MS_BioDiversityMgmtSetup.Modify(true); 191 | end; 192 | 193 | local procedure FinishAction(); 194 | begin 195 | StoreRecordVar(); 196 | CurrPage.Close(); 197 | end; 198 | 199 | local procedure NextStep(Backwards: Boolean); 200 | begin 201 | if Backwards then 202 | Step := Step - 1 203 | else 204 | Step := Step + 1; 205 | 206 | EnableControls(); 207 | end; 208 | 209 | local procedure ShowStep1(); 210 | begin 211 | Step1Visible := true; 212 | 213 | FinishActionEnabled := false; 214 | BackActionEnabled := false; 215 | end; 216 | 217 | local procedure ShowStep2(); 218 | begin 219 | Step2Visible := true; 220 | end; 221 | 222 | local procedure ShowStep3(); 223 | begin 224 | Step3Visible := true; 225 | 226 | NextActionEnabled := false; 227 | FinishActionEnabled := true; 228 | end; 229 | 230 | local procedure ResetControls(); 231 | begin 232 | FinishActionEnabled := false; 233 | BackActionEnabled := true; 234 | NextActionEnabled := true; 235 | 236 | Step1Visible := false; 237 | Step2Visible := false; 238 | Step3Visible := false; 239 | end; 240 | 241 | local procedure LoadTopBanners(); 242 | begin 243 | if MediaRepositoryStandard.Get('AssistedSetup-NoText-400px.png', Format(CurrentClientType())) and 244 | MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', Format(CurrentClientType())) 245 | then 246 | if MediaResourcesStandard.Get(MediaRepositoryStandard."Media Resources Ref") and 247 | MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref") 248 | then 249 | TopBannerVisible := MediaResourcesDone."Media Reference".HasValue(); 250 | end; 251 | } -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtSetupList.Codeunit.al: -------------------------------------------------------------------------------- 1 | codeunit 70074176 MS_BioDiversityMgmtSetupList 2 | { 3 | trigger OnRun() 4 | var 5 | BioDiversitySetup: Record MS_BioDiversityMgmtSetup; 6 | GuidedExperience: Codeunit "Guided Experience"; 7 | SetupKey: Code[20]; 8 | HttpClient: HttpClient; 9 | ResponseMsg: HttpResponseMessage; 10 | OutStream: OutStream; 11 | InStream: InStream; 12 | 13 | begin 14 | //First, enable the overall setup of the module if not already enabled 15 | SetupKey := 'BIODIVSETUP'; 16 | if not BioDiversitySetup.Get(SetupKey) then begin 17 | BioDiversitySetup.Init(); 18 | BioDiversitySetup.PrimaryKey := SetupKey; 19 | BioDiversitySetup.Enabled := true; 20 | BioDiversitySetup.Insert(); 21 | Commit(); 22 | end; 23 | 24 | //if HttpClient.Get('https://github.com/microsoft/bcsamples-onboarding/tree/main/Media/Resources/wizardbanner.jpg', ResponseMsg) then 25 | if HttpClient.Get('https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/main/Media/Resources/wizardbanner.png', ResponseMsg) then 26 | ResponseMsg.Content.ReadAs(InStream); 27 | 28 | if ResponseMsg.IsSuccessStatusCode then begin 29 | BioDiversitySetup.SetupWizardBanner.CreateOutStream(OutStream); 30 | CopyStream(OutStream, InStream); 31 | BioDiversitySetup.Modify(); 32 | Commit(); 33 | end; 34 | 35 | GuidedExperience.OpenAssistedSetup(Enum::"Assisted Setup Group"::MS_BioDiversity); 36 | end; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /App/MSBioDiversityMgmtWelcomeExperience.Codeunit.al: -------------------------------------------------------------------------------- 1 | codeunit 70074170 MS_CreateWelcomeExperience 2 | { 3 | var 4 | //Define the texts for the Guided Experience Items the users will see in their checklists 5 | //If the user has profiled as coming from Excel, we want to show them a checklist item that makes them feel welcomed right off the bat 6 | SystemShortTitleTxt: Label 'Excel users love us'; 7 | SystemTitleTxt: Label 'Easily work with plant data in Excel'; 8 | SystemDescriptionTxt: Label 'With a seamless integration to Excel, you can easily work with data in Excel, and even import it back into Business Central. Great for manipulating lists of data.'; 9 | 10 | //Depending on the user's company profile, add a Guided Experience Item that shows we know what they care about 11 | UsersShortTitleTxt: Label 'So, you have 10-25 users?'; 12 | UsersTitleTxt: Label 'Your company is a great fit for Business Central'; 13 | UsersDescriptionTxt: Label 'Business Central is great for companies with a user base of 10-25, but it does not stop there. Business Central empowers you to grow your business. See the video to learn how.'; 14 | 15 | //When the user answered questions in the profiler (on your web site), ask them what they're looking for, and load a Guided Experience Item that confirms they've gone to the right place 16 | InterestShortTitleTxt: Label 'Become a champion'; 17 | InterestTitleTxt: Label 'Bio Diversity Mgmt. will assist you'; 18 | InterestDescriptionTxt: Label 'In this short video we will show you how Bio Diversity Management can help you become a champion for bio diversity and help make the World a better place.'; 19 | 20 | OnboardingSampleValueTxt: Label 'bcsamples-onboarding', Locked = true; 21 | 22 | 23 | //This event is used to set the sign-up context. 24 | //This happens at system initialization. 25 | //In a normal standard trial provisioning where this app is not installed, the sign-up context is set in standard Microsoft code. 26 | //In that scenario the sign-up context key/value pair is "name": "viral". 27 | //But in our scenario our app is installed when the BC trial is provisioned, so we have the opportunity to set our own sign-up context. 28 | //Why would we want to do that? Because the context allows us to pivot the experience. 29 | //You could even have multiple contexts. Imagine you profile potential customers on your web site and depending on their answers you load different experiences. 30 | //This is managed by th sign-up context. 31 | //With the event below we can set the sign-up context when the system initializes, so that we will know later on what we should react to. 32 | //Think of the signup context being a result of company profiling = determines _which_ app and _which_business scenario to load (industry, etc.) 33 | [EventSubscriber(ObjectType::Codeunit, Codeunit::"System Initialization", 'OnSetSignupContext', '', false, false)] 34 | local procedure SetSignupContext() 35 | var 36 | SignupContextValues: Record "Signup Context Values"; 37 | SignupContext: Record "Signup Context"; 38 | AllProfile: Record "All Profile"; 39 | Checklist: Codeunit Checklist; 40 | SpotlightTourType: Enum "Spotlight Tour Type"; 41 | GuidedExperienceType: Enum "Guided Experience Type"; 42 | begin 43 | //First, we check if BC was provisioned via a URL that contained a sign-up context name (= the name is stored in the Signup Context table) 44 | if not SignupContext.Get('name') then 45 | FakeTestsWhenNotInSignup(); 46 | 47 | if not (LowerCase(SignupContext.Value) = OnboardingSampleValueTxt) then 48 | exit; 49 | 50 | Clear(SignupContextValues); 51 | if not SignupContextValues.IsEmpty() then 52 | exit; 53 | 54 | AddGuidedExperienceItems(); 55 | 56 | //Now, we set our desired context. The context should identify your app. One app, one context. 57 | //Note, that you can react to other key value pairs if you want to do things depending on profiler answers. 58 | SignupContextValues."Signup Context" := SignupContextValues."Signup Context"::MS_BioDiversityMgmt; 59 | SignupContextValues.Insert(); 60 | 61 | //Wwe read the SignupContext table where the profiler answers have been stored via the signupContext parameter in the URL when they started BC for the first time 62 | 63 | /* --- DO STUFF BASED ON THE CUSTOMER PROFILE --- 64 | Here is where you check the SignupContext table for the profiler answers. 65 | Imagine you have a web site where you ask for: 66 | - Which system do you use today? 67 | - What is your interest / would you like to see / expect to find in BC? 68 | - How many users are in your company? 69 | 70 | Based on the answers to those questions we want to show different things in the checklist, in the welcome banner texts, tours etc. 71 | 72 | When you have the answers from your profiling (for example from a form on your web site) you must construct a URL with a correct signupContext. 73 | Read more about how to do that here: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/onboarding-signupcontext 74 | 75 | If you have done this right the answers from the customer profiling will be stored in a system table, "Signup Context". 76 | This means you can read them and determine what the customer answered and use those answers to pivot the experience. 77 | 78 | Let's give the user what they expect, no? :o) 79 | */ 80 | 81 | //If the user said they use Excel today, create the checklist item from the Guided Experience Item we added above that shows why BC is great with Excel 82 | SignupContext.Reset(); 83 | SignupContext.SetRange(SignupContext.KeyName, 'currentsystem'); //this key can be anything but has to match the output of your profiling, what you added to the URL based on the answers provided by the user 84 | SignupContext.SetRange(SignupContext.Value, 'Excel'); //This is an example of the profiler answer 85 | if SignupContext.FindSet() then begin 86 | Checklist.Insert(Page::"Vendor List", SpotlightTourType::"Open in Excel", 1000, AllProfile, false); 87 | Checklist.Insert(GuidedExperienceType::"Application Feature", ObjectType::Report, Report::MS_BioDiversityPlant, 3000, AllProfile, false); 88 | end; 89 | 90 | //If they have told us they're looking for "Bio Diversity", let's show them something meaningful 91 | SignupContext.Reset(); 92 | SignupContext.SetRange(SignupContext.KeyName, 'interest'); 93 | SignupContext.SetRange(SignupContext.Value, 'Bio Diversity'); 94 | if SignupContext.FindSet() then begin 95 | Checklist.Insert(GuidedExperienceType::"Application Feature", ObjectType::Codeunit, Codeunit::MS_BioDiversityMgmtSetupList, 2000, AllProfile, false); 96 | Checklist.Insert(GuidedExperienceType::Video, 'https://www.youtube.com/embed/YpWD4ZrLobI', 4000, AllProfile, false); 97 | Checklist.Insert(GuidedExperienceType::Tour, ObjectType::Page, Page::MS_BioDiversityMgmtPlants, 5000, AllProfile, false); 98 | end; 99 | 100 | //Let's speak their language with a great video, if they say they're 10-25 users in the company 101 | SignupContext.Reset(); 102 | SignupContext.SetRange(SignupContext.KeyName, 'users'); 103 | SignupContext.SetRange(SignupContext.Value, '10-25'); 104 | if SignupContext.IsEmpty() then 105 | Checklist.Insert(GuidedExperienceType::Video, 'https://www.youtube.com/embed/nqM79hlHuOs', 8000, AllProfile, false); 106 | 107 | end; 108 | 109 | 110 | //This event lets you override the texts on the welcome banner. Use it to create that warm fuzzy feeling for users who see the role center for the first time 111 | [EventSubscriber(ObjectType::Codeunit, Codeunit::"Checklist Banner", 'OnBeforeUpdateBannerLabels', '', false, false)] 112 | local procedure OnBeforeUpdateBannerLabels(var IsHandled: Boolean; IsEvaluationCompany: Boolean; var TitleTxt: Text; var TitleCollapsedTxt: Text; var HeaderTxt: Text; var HeaderCollapsedTxt: Text; var DescriptionTxt: Text) 113 | var 114 | User: Record User; 115 | begin 116 | IsHandled := true; 117 | 118 | User.Reset(); 119 | User.SetRange(User."User Security ID", Database.UserSecurityId()); 120 | User.FindFirst(); 121 | 122 | TitleTxt := 'Welcome ' + User."Full Name" + '!'; 123 | TitleCollapsedTxt := 'Continue your experience'; 124 | HeaderTxt := 'Want to help save the World? So do we! 🌍'; 125 | HeaderCollapsedTxt := 'Continue setting up your system'; 126 | DescriptionTxt := 'You started a trial for Business Central with Bio Diversity Management. We hope you''ll love it!'; 127 | end; 128 | 129 | 130 | //Here we create the dictionary of texts used for the Spotlight tour where we call out the Excel integration (which we use on the Vendor List) 131 | local procedure GetVendorListSpotlightTourDictionary(var SpotlightTourTexts: Dictionary of [Enum "Spotlight Tour Text", Text]) 132 | var 133 | EditPlantsInExcelStep1TitleTxt: Label 'Easily analyse any list data in Excel. For example this list of plants.'; 134 | EditPlantsInExcelStep1DescrTxt: Label 'You can export any list to Excel - even Excel online. You can also edit data in Excel'; 135 | EditPlantsInExcelStep2TitleTxt: Label 'Here you''ll find actions to open lists and cards in other applications'; 136 | EditPlantsInExcelStep2DescrTxt: Label 'Try editing this list of plants in Excel and import it back into Business Central'; 137 | SpotlightTourText: Enum "Spotlight Tour Text"; 138 | begin 139 | SpotlightTourTexts.Add(SpotlightTourText::Step1Title, EditPlantsInExcelStep1TitleTxt); 140 | SpotlightTourTexts.Add(SpotlightTourText::Step1Text, EditPlantsInExcelStep1DescrTxt); 141 | SpotlightTourTexts.Add(SpotlightTourText::Step2Title, EditPlantsInExcelStep2TitleTxt); 142 | SpotlightTourTexts.Add(SpotlightTourText::Step2Text, EditPlantsInExcelStep2DescrTxt); 143 | end; 144 | 145 | internal procedure FakeTestsWhenNotInSignup() 146 | var 147 | //Define variables we need to insert Checklists 148 | AllProfile: Record "All Profile"; 149 | Checklist: Codeunit Checklist; 150 | SpotlightTourType: Enum "Spotlight Tour Type"; 151 | GuidedExperienceType: Enum "Guided Experience Type"; 152 | begin 153 | AddGuidedExperienceItems(); 154 | Checklist.Insert(GuidedExperienceType::Video, 'https://www.youtube.com/embed/YpWD4ZrLobI', 1000, AllProfile, false); 155 | Checklist.Insert(GuidedExperienceType::"Application Feature", ObjectType::Codeunit, Codeunit::MS_BioDiversityMgmtSetupList, 2000, AllProfile, false); 156 | Checklist.Insert(Page::MS_BioDiversityMgmtPlants, SpotlightTourType::"Open in Excel", 3000, AllProfile, false); 157 | Checklist.Insert(GuidedExperienceType::"Application Feature", ObjectType::Report, Report::MS_BioDiversityPlant, 4000, AllProfile, false); 158 | Checklist.Insert(GuidedExperienceType::Tour, ObjectType::Page, Page::MS_BioDiversityMgmtPlants, 5000, AllProfile, false); 159 | Checklist.Insert(GuidedExperienceType::Video, 'https://www.youtube.com/embed/nqM79hlHuOs', 6000, AllProfile, false); 160 | end; 161 | 162 | internal procedure AddGuidedExperienceItems() 163 | var 164 | //Define variables we need to insert Guided Experience Items 165 | GuidedExperience: Codeunit "Guided Experience"; 166 | VideoCategory: Enum "Video Category"; 167 | AssistedSetupGroup: Enum "Assisted Setup Group"; 168 | SpotlightTourType: Enum "Spotlight Tour Type"; 169 | GuidedExperienceType: Enum "Guided Experience Type"; 170 | SpotlightTourTexts: Dictionary of [Enum "Spotlight Tour Text", Text]; 171 | DefineInsectsTitle: Text; 172 | DefineInsectsShortTitle: Text; 173 | DefineInsectsDescription: Text; 174 | DefinePlantsTitle: Text; 175 | DefinePlantsShortTitle: Text; 176 | DefinePlantsDescription: Text; 177 | BioDiversityMgmtSetuplistTitle: Text; 178 | BioDiversityMgmtSetuplistShortTitle: Text; 179 | BioDiversityMgmtSetuplistDescription: Text; 180 | PlantReportTitle: text; 181 | PlantReportShortTitle: text; 182 | PlantReportDescription: text; 183 | PlantsPageTitle: text; 184 | PlantsPageShortTitle: text; 185 | PlantsPageDescription: text; 186 | begin 187 | //Add our Guided Experience Items we want to potentially add to the checklist 188 | //Add the guided experience items. Note, that here we just load three different videos for the "system", "users" and "interest" questions from the profiler 189 | //Add the checklist items you think makes sense to greet the user with, based on their profile. 190 | DefineInsectsTitle := '1: Define the list of insects you want to work with'; 191 | DefineInsectsShortTitle := '1: Get the list of insects from Github'; 192 | DefineInsectsDescription := 'Insects play a crucial role in bio diversity. Start tracking them today! Import a list of known insects from Github here.'; 193 | DefinePlantsTitle := '2: Let us define the list of plants you want to work with'; 194 | DefinePlantsShortTitle := '1: Get the list of plants from Github'; 195 | DefinePlantsDescription := 'Plants play a crucial role in bio diversity. Start tracking them today! Import a list of known plants from Github here.'; 196 | BioDiversityMgmtSetuplistTitle := 'Set up Bio Diversity Management'; 197 | BioDiversityMgmtSetuplistShortTitle := 'Start tracking bio diversity'; 198 | BioDiversityMgmtSetuplistDescription := 'We have created a nice and easy checklist of what you need to set up Bio Diversity Management. We will guide you every step of the way!'; 199 | PlantReportTitle := 'Track your plants in the ecosystem'; 200 | PlantReportShortTitle := 'Track your plants'; 201 | PlantReportDescription := 'Track your list of plants and their occurence in a board ready report. Bio diversity management has never been easier!'; 202 | PlantsPageTitle := 'Manage your plants lifecycle here'; 203 | PlantsPageShortTitle := 'Plants lifecycle'; 204 | PlantsPageDescription := 'Manage and analyze your plants here, so you are always on top of the health of the ecosystem you are managing.'; 205 | 206 | //Clean up before we add 207 | GuidedExperience.Remove(GuidedExperienceType::"Assisted Setup", ObjectType::Page, Page::MS_BioDiversityMgmtInsectGuide); 208 | GuidedExperience.Remove(GuidedExperienceType::"Assisted Setup", ObjectType::Page, Page::MS_BioDiversityMgmtPlantGuide); 209 | GuidedExperience.Remove(GuidedExperienceType::"Assisted Setup", ObjectType::Report, Report::MS_BioDiversityPlant); 210 | 211 | GetVendorListSpotlightTourDictionary(SpotlightTourTexts); 212 | GuidedExperience.InsertSpotlightTour(SystemTitleTxt, SystemShortTitleTxt, SystemDescriptionTxt, 2, Page::MS_BioDiversityMgmtPlants, SpotlightTourType::"Open in Excel", SpotlightTourTexts); 213 | GuidedExperience.InsertVideo(UsersTitleTxt, UsersShortTitleTxt, UsersDescriptionTxt, 1, 'https://www.youtube.com/embed/nqM79hlHuOs', VideoCategory::GettingStarted); 214 | GuidedExperience.InsertVideo(InterestTitleTxt, InterestShortTitleTxt, InterestDescriptionTxt, 1, 'https://www.youtube.com/embed/YpWD4ZrLobI', VideoCategory::GettingStarted); 215 | GuidedExperience.InsertAssistedSetup(DefineInsectsTitle, DefineInsectsShortTitle, DefineInsectsDescription, 1, ObjectType::Page, Page::MS_BioDiversityMgmtInsectGuide, AssistedSetupGroup::MS_BioDiversity, '', VideoCategory::GettingStarted, ''); 216 | GuidedExperience.InsertAssistedSetup(DefinePlantsTitle, DefinePlantsShortTitle, DefinePlantsDescription, 1, ObjectType::Page, Page::MS_BioDiversityMgmtPlantGuide, AssistedSetupGroup::MS_BioDiversity, '', VideoCategory::GettingStarted, ''); 217 | GuidedExperience.InsertApplicationFeature(BioDiversityMgmtSetuplistTitle, BioDiversityMgmtSetuplistShortTitle, BioDiversityMgmtSetuplistDescription, 1, ObjectType::Codeunit, Codeunit::MS_BioDiversityMgmtSetupList); 218 | GuidedExperience.InsertApplicationFeature(PlantReportTitle, PlantReportShortTitle, PlantReportDescription, 1, ObjectType::Report, report::MS_BioDiversityPlant); 219 | GuidedExperience.InsertTour(PlantsPageTitle, PlantsPageShortTitle, PlantsPageDescription, 3, Page::MS_BioDiversityMgmtPlants); 220 | 221 | end; 222 | 223 | [EventSubscriber(ObjectType::Codeunit, Codeunit::"User Triggers", 'OnAfterUserInitialization', '', false, false)] 224 | local procedure OnAfterUserInitialization() 225 | begin 226 | SetCurrentUserRole(); 227 | end; 228 | 229 | internal procedure GetThisAppID(): guid 230 | begin 231 | exit('{cf6719a0-2f10-48dd-93b2-a1f4b0647cbf}'); 232 | end; 233 | 234 | internal procedure SetCurrentUserRole() 235 | var 236 | UserPersonalization: Record "User Personalization"; 237 | begin 238 | if not UserPersonalization.Get(UserSecurityId()) then begin 239 | UserPersonalization."User SID" := UserSecurityId(); 240 | UserPersonalization."User ID" := UserId(); 241 | UserPersonalization."App ID" := GetThisAppID(); 242 | UserPersonalization.Scope := UserPersonalization.Scope::Tenant; 243 | UserPersonalization.Role := 'Bio Diversity Manager'; 244 | UserPersonalization."Profile ID" := 'MS_BIODIVERSITYMGMTPROFILE'; 245 | UserPersonalization.Insert(); 246 | end else begin 247 | UserPersonalization.Scope := UserPersonalization.Scope::Tenant; 248 | UserPersonalization."App ID" := GetThisAppID(); 249 | UserPersonalization.Role := 'Bio Diversity Manager'; 250 | UserPersonalization."Profile ID" := 'MS_BIODIVERSITYMGMTPROFILE'; 251 | UserPersonalization.Modify(); 252 | end; 253 | end; 254 | } 255 | -------------------------------------------------------------------------------- /App/MSBioDiversityPlant.Report.al: -------------------------------------------------------------------------------- 1 | report 70074170 MS_BioDiversityPlant 2 | { 3 | UsageCategory = ReportsAndAnalysis; 4 | ApplicationArea = All; 5 | DefaultRenderingLayout = DefaultLayout; 6 | Caption = 'Bio Diversity Tracking'; 7 | 8 | dataset 9 | { 10 | dataitem(Plants; MS_BioDiversityMgmtPlant) 11 | { 12 | column(PlantCode; PlantCode) 13 | { 14 | } 15 | column(Occurrences; Occurrences) 16 | { 17 | } 18 | column(Name; Name) 19 | { 20 | } 21 | column(Description; Description) 22 | { 23 | } 24 | column(IsPollinator; IsPollinator) 25 | { 26 | } 27 | column(PollinatedBy; PollinatedBy) 28 | { 29 | } 30 | column(Family; Family) 31 | { 32 | } 33 | } 34 | } 35 | 36 | requestpage 37 | { 38 | AboutTitle = 'Track Bio Diversity progress'; 39 | AboutText = 'Here you can track you *bio diversity progress*. This list is focused on **plants**. Printing to an Excel layout let''s you create beautiful looking visualizations which you know and love in *Excel*, updated with fresh data when you print.'; 40 | 41 | layout 42 | { 43 | area(Content) 44 | { 45 | group(GroupName) 46 | { 47 | field(PlantCode; PlantCodeFilter) 48 | { 49 | ApplicationArea = All; 50 | Caption = 'PlantCode Filter'; 51 | ToolTip = 'PlantCode Filter'; 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | rendering 59 | { 60 | layout(DefaultLayout) 61 | { 62 | Type = Excel; 63 | LayoutFile = 'BioDiversityPlant.xlsx'; 64 | } 65 | } 66 | 67 | var 68 | PlantCodeFilter: Code[30]; 69 | } -------------------------------------------------------------------------------- /App/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cf6719a0-2f10-48dd-93b2-a1f4b0647cbf", 3 | "name": "Onboarding Sample App", 4 | "publisher": "Søren Alexandersen", 5 | "version": "1.0.1.0", 6 | "brief": "Sample app that showcase how to create a great welcome experience for Business Central customers", 7 | "description": "This app show examples of using several elements of the onboarding framework for Business Central.", 8 | "privacyStatement": "https://go.microsoft.com/fwlink/?LinkId=834881", 9 | "EULA": "https://github.com/microsoft/bcsamples-onboarding/blob/main/LICENSE", 10 | "help": "https://github.com/microsoft/bcsamples-onboarding", 11 | "url": "https://github.com/microsoft/bcsamples-onboarding", 12 | "logo": "../Media/Logo/logo.png", 13 | "dependencies": [], 14 | "screenshots": [], 15 | "platform": "22.0.0.0", 16 | "application": "23.0.0.0", 17 | "runtime": "12.0", 18 | "contextSensitiveHelpUrl": "https://github.com/microsoft/bcsamples-onboarding", 19 | "idRanges": [ 20 | { 21 | "from": 70074170, 22 | "to": 70074189 23 | } 24 | ], 25 | "features": [ 26 | "NoImplicitWith", "TranslationFile", "GenerateCaptions" 27 | ], 28 | "resourceExposurePolicy": { 29 | "allowDebugging": true, 30 | "allowDownloadingSource": false, 31 | "includeSourceInSymbolFile": false 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /App/plants.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "plants":[ 4 | { 5 | "Name": "Alpine Meadow-Rue", 6 | "Plant Characteristics": "Perennial herbaceous plant", 7 | "Family Name": "Ranunculaceae", 8 | "Family Description": "Large family of flowering plants", 9 | "Family Characteristics": "Showy, colorful flowers" 10 | }, 11 | { 12 | "Name": "Cowslip", 13 | "Plant Characteristics": "Perennial herbaceous plant", 14 | "Family Name": "Primulaceae", 15 | "Family Description": "Family of flowering plants", 16 | "Family Characteristics": "Showy, fragrant flowers" 17 | }, 18 | { 19 | "Name": "Dwarf Cornel", 20 | "Plant Characteristics": "Small shrub", 21 | "Family Name": "Cornaceae", 22 | "Family Description": "Family of flowering plants", 23 | "Family Characteristics": "Showy, fragrant flowers" 24 | }, 25 | { 26 | "Name": "European White Birch", 27 | "Plant Characteristics": "Tree", 28 | "Family Name": "Betulaceae", 29 | "Family Description": "Family of flowering plants", 30 | "Family Characteristics": "Showy, fragrant flowers" 31 | }, 32 | { 33 | "Name": "Common Field Speedwell", 34 | "Plant Characteristics": "Herbaceous annual plant", 35 | "Family Name": "Plantaginaceae", 36 | "Family Description": "Family of flowering plants", 37 | "Family Characteristics": "Showy, fragrant flowers" 38 | }, 39 | { 40 | "Name": "Common Ragwort", 41 | "Plant Characteristics": "Herbaceous biennial plant", 42 | "Family Name": "Asteraceae", 43 | "Family Description": "Large family of flowering plants", 44 | "Family Characteristics": "Showy, colorful flowers" 45 | }, 46 | { 47 | "Name": "Common St. John's Wort", 48 | "Plant Characteristics": "Herbaceous perennial plant", 49 | "Family Name": "Hypericaceae", 50 | "Family Description": "Family of flowering plants", 51 | "Family Characteristics": "Showy, fragrant flowers" 52 | }, 53 | { 54 | "Name": "Common Valerian", 55 | "Plant Characteristics": "Herbaceous perennial plant", 56 | "Family Name": "Valerianaceae", 57 | "Family Description": "Family of flowering plants", 58 | "Family Characteristics": "Showy, fragrant flowers" 59 | }, 60 | { 61 | "Name": "Crested Hair-Grass", 62 | "Plant Characteristics": "Grass", 63 | "Family Name": "Poaceae", 64 | "Family Description": "Large family of flowering plants", 65 | "Family Characteristics": "Showy, colorful flowers" 66 | }, 67 | { 68 | "Name": "Dyer's Greenweed", 69 | "Plant Characteristics": "Herbaceous annual plant", 70 | "Family Name": "Fabaceae", 71 | "Family Description": "Large family of flowering plants", 72 | "Family Characteristics": "Showy, colorful flowers" 73 | }, 74 | { 75 | "Name": "European Alder", 76 | "Plant Characteristics": "Tree", 77 | "Family Name": "Betulaceae", 78 | "Family Description": "Family of flowering plants", 79 | "Family Characteristics": "Showy, fragrant flowers" 80 | }, 81 | { 82 | "Name": "European Beech", 83 | "Plant Characteristics": "Tree", 84 | "Family Name": "Fagaceae", 85 | "Family Description": "Family of flowering plants", 86 | "Family Characteristics": "Showy, fragrant flowers" 87 | }, 88 | { 89 | "Name": "European Hornbeam", 90 | "Plant Characteristics": "Tree", 91 | "Family Name": "Carpinaceae", 92 | "Family Description": "Family of flowering plants", 93 | "Family Characteristics": "Showy, fragrant flowers" 94 | }, 95 | { 96 | "Name": "European Larch", 97 | "Plant Characteristics": "Tree", 98 | "Family Name": "Pinaceae", 99 | "Family Description": "Family of flowering plants", 100 | "Family Characteristics": "Showy, fragrant flowers" 101 | }, 102 | { 103 | "Name": "European White Elm", 104 | "Plant Characteristics": "Tree", 105 | "Family Name": "Ulmaceae", 106 | "Family Description": "Family of flowering plants", 107 | "Family Characteristics": "Showy, fragrant flowers" 108 | }, 109 | { 110 | "Name": "Fairy Foxglove", 111 | "Plant Characteristics": "Herbaceous biennial plant", 112 | "Family Name": "Scrophulariaceae", 113 | "Family Description": "Family of flowering plants", 114 | "Family Characteristics": "Showy, fragrant flowers" 115 | }, 116 | { 117 | "Name": "Field Bindweed", 118 | "Plant Characteristics": "Herbaceous perennial plant", 119 | "Family Name": "Convolvulaceae", 120 | "Family Description": "Family of flowering plants", 121 | "Family Characteristics": "Showy, fragrant flowers" 122 | }, 123 | { 124 | "Name": "Field Scabious", 125 | "Plant Characteristics": "Herbaceous perennial plant", 126 | "Family Name": "Dipsacaceae", 127 | "Family Description": "Family of flowering plants", 128 | "Family Characteristics": "Showy, fragrant flowers" 129 | }, 130 | { 131 | "Name": "Field Wood-Rush", 132 | "Plant Characteristics": "Herbaceous perennial plant", 133 | "Family Name": "Juncaceae", 134 | "Family Description": "Family of flowering plants", 135 | "Family Characteristics": "Showy, fragrant flowers" 136 | }, 137 | { 138 | "Name": "Greater Burnet-Saxifrage", 139 | "Plant Characteristics": "Herbaceous perennial plant", 140 | "Family Name": "Saxifragaceae", 141 | "Family Description": "Family of flowering plants", 142 | "Family Characteristics": "Showy, fragrant flowers" 143 | }, 144 | { 145 | "Name": "Greater Plantain", 146 | "Plant Characteristics": "Herbaceous perennial plant", 147 | "Family Name": "Plantaginaceae", 148 | "Family Description": "Family of flowering plants", 149 | "Family Characteristics": "Showy, fragrant flowers" 150 | }, 151 | { 152 | "Name": "Harebell", 153 | "Plant Characteristics": "Herbaceous perennial plant", 154 | "Family Name": "Campanulaceae", 155 | "Family Description": "Family of flowering plants", 156 | "Family Characteristics": "Showy, fragrant flowers" 157 | }, 158 | { 159 | "Name": "Heath Speedwell", 160 | "Plant Characteristics": "Herbaceous annual plant", 161 | "Family Name": "Plantaginaceae", 162 | "Family Description": "Family of flowering plants", 163 | "Family Characteristics": "Showy, fragrant flowers" 164 | }, 165 | { 166 | "Name": "Hoary Plantain", 167 | "Plant Characteristics": "Herbaceous perennial plant", 168 | "Family Name": "Plantaginaceae", 169 | "Family Description": "Family of flowering plants", 170 | "Family Characteristics": "Showy, fragrant flowers" 171 | }, 172 | { 173 | "Name": "Italian Alder", 174 | "Plant Characteristics": "Tree", 175 | "Family Name": "Betulaceae", 176 | "Family Description": "Family of flowering plants", 177 | "Family Characteristics": "Showy, fragrant flowers" 178 | }, 179 | { 180 | "Name": "Italian Asphodel", 181 | "Plant Characteristics": "Herbaceous perennial plant", 182 | "Family Name": "Asphodelaceae", 183 | "Family Description": "Family of flowering plants", 184 | "Family Characteristics": "Showy, fragrant flowers" 185 | }, 186 | { 187 | "Name": "Lesser Celandine", 188 | "Plant Characteristics": "Herbaceous perennial plant", 189 | "Family Name": "Ranunculaceae", 190 | "Family Description": "Large family of flowering plants", 191 | "Family Characteristics": "Showy, colorful flowers" 192 | }, 193 | { 194 | "Name": "Meadow Buttercup", 195 | "Plant Characteristics": "Herbaceous perennial plant", 196 | "Family Name": "Ranunculaceae", 197 | "Family Description": "Large family of flowering plants", 198 | "Family Characteristics": "Showy, colorful flowers" 199 | }, 200 | { 201 | "Name": "Meadow Cranesbill", 202 | "Plant Characteristics": "Herbaceous perennial plant", 203 | "Family Name": "Geraniaceae", 204 | "Family Description": "Family of flowering plants", 205 | "Family Characteristics": "Showy, fragrant flowers" 206 | }, 207 | { 208 | "Name": "Meadow Foxtail", 209 | "Plant Characteristics": "Grass", 210 | "Family Name": "Poaceae", 211 | "Family Description": "Large family of flowering plants", 212 | "Family Characteristics": "Showy, colorful flowers" 213 | }, 214 | { 215 | "Name": "Meadow Vetchling", 216 | "Plant Characteristics": "Herbaceous annual plant", 217 | "Family Name": "Fabaceae", 218 | "Family Description": "Large family of flowering plants", 219 | "Family Characteristics": "Showy, colorful flowers" 220 | }, 221 | { 222 | "Name": "Mountain Avens", 223 | "Plant Characteristics": "Herbaceous perennial plant", 224 | "Family Name": "Rosaceae", 225 | "Family Description": "Large family of flowering plants", 226 | "Family Characteristics": "Showy, colorful flowers" 227 | }, 228 | { 229 | "Name": "Mountain Melick", 230 | "Plant Characteristics": "Herbaceous annual plant", 231 | "Family Name": "Fabaceae", 232 | "Family Description": "Large family of flowering plants", 233 | "Family Characteristics": "Showy, colorful flowers" 234 | }, 235 | { 236 | "Name": "Ox-Eye Daisy", 237 | "Plant Characteristics": "Herbaceous perennial plant", 238 | "Family Name": "Asteraceae", 239 | "Family Description": "Large family of flowering plants", 240 | "Family Characteristics": "Showy, colorful flowers" 241 | }, 242 | { 243 | "Name": "Pale Flax", 244 | "Plant Characteristics": "Herbaceous annual plant", 245 | "Family Name": "Linaceae", 246 | "Family Description": "Family of flowering plants", 247 | "Family Characteristics": "Showy, fragrant flowers" 248 | }, 249 | { 250 | "Name": "Purple Milk-Vetch", 251 | "Plant Characteristics": "Herbaceous annual plant", 252 | "Family Name": "Fabaceae", 253 | "Family Description": "Large family of flowering plants", 254 | "Family Characteristics": "Showy, colorful flowers" 255 | }, 256 | { 257 | "Name": "Ramsons", 258 | "Plant Characteristics": "Herbaceous perennial plant", 259 | "Family Name": "Alliaceae", 260 | "Family Description": "Family of flowering plants", 261 | "Family Characteristics": "Showy, fragrant flowers" 262 | } 263 | ] 264 | } -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/dynamics-smb-engineering-systems 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /Media/Github Sample Banner/Sample banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Github Sample Banner/Sample banner.png -------------------------------------------------------------------------------- /Media/Logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Logo/logo.png -------------------------------------------------------------------------------- /Media/Resources/wizardbanner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Resources/wizardbanner.jpg -------------------------------------------------------------------------------- /Media/Resources/wizardbanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Resources/wizardbanner.png -------------------------------------------------------------------------------- /Media/Screenshots/ChecklistItemFromProfiling1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Screenshots/ChecklistItemFromProfiling1.png -------------------------------------------------------------------------------- /Media/Screenshots/ChecklistItemFromProfiling2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Screenshots/ChecklistItemFromProfiling2.png -------------------------------------------------------------------------------- /Media/Screenshots/ChecklistItemFromProfiling3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Screenshots/ChecklistItemFromProfiling3.png -------------------------------------------------------------------------------- /Media/Screenshots/ModifyWelcomeBannerTexts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/bcsamples-onboarding/1b9b3cc46d16d68dbca2fe6a3ab41b456b8d7d12/Media/Screenshots/ModifyWelcomeBannerTexts.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | Welcome to the repo Onboarding sample app for Business Central. 4 | This intention with this code is to: 5 | 6 | - Inspire ISVs and developers to use elements of the onboarding framework 7 | - Add interesting scenarios that helps ISVs and resellers onboard customers faster 8 | 9 | Feel free to contribute to this repo! 10 | 11 | ## Contributing 12 | 13 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 14 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 15 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 16 | 17 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 18 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 19 | provided by the bot. You will only need to do this once across all repos using our CLA. 20 | 21 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 23 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 24 | 25 | ## Trademarks 26 | 27 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft 28 | trademarks or logos is subject to and must follow 29 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). 30 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. 31 | Any use of third-party trademarks or logos are subject to those third-party's policies. 32 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # TODO: The maintainer of this repo has not yet edited this file 2 | 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? 4 | 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help. 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. 7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. 8 | 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.* 10 | 11 | # Support 12 | 13 | ## How to file issues and get help 14 | 15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 17 | feature request as a new Issue. 18 | 19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER 21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**. 22 | 23 | ## Microsoft Support Policy 24 | 25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 26 | -------------------------------------------------------------------------------- /al.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".AL-Go" 5 | }, 6 | { 7 | "path": "App" 8 | } 9 | ], 10 | "settings": { 11 | 12 | } 13 | } 14 | --------------------------------------------------------------------------------