├── CODEOWNERS ├── App ├── permissionsAnalyzer.json ├── .vscode │ ├── extensions.json │ └── settings.json ├── AppSourceCop.json ├── src │ ├── Addin │ │ ├── Script │ │ │ ├── Interface.js │ │ │ ├── Utility.js │ │ │ ├── Startup.js │ │ │ └── Widgetbot.js │ │ └── Widgetbot.ControlAddin.al │ ├── Permissions │ │ └── User.PermissionSet.al │ └── WidgetbotSetup.Codeunit.al ├── .codeanalysis │ └── ignoreRuleset.ruleset.json └── app.json ├── Demo ├── permissionsAnalyzer.json ├── .vscode │ ├── extensions.json │ └── settings.json ├── AppSourceCop.json ├── src │ ├── Install&Upgrade │ │ ├── Install.Codeunit.al │ │ └── Upgrade.Codeunit.al │ ├── Permissions │ │ ├── Basic.PermissionSetExt.al │ │ └── User.PermissionSet.al │ └── App.Page.al ├── .codeanalysis │ └── ignoreRuleset.ruleset.json └── app.json ├── Test ├── permissionsAnalyzer.json ├── .vscode │ ├── extensions.json │ └── settings.json ├── AppSourceCop.json ├── src │ └── Install&Upgrade │ │ ├── Install.Codeunit.al │ │ └── Upgrade.Codeunit.al ├── .codeanalysis │ └── ignoreRuleset.ruleset.json ├── app.json ├── test │ └── Setup.Codeunit.al └── lib │ └── Helper.Codeunit.al ├── assets └── discord_banner.png ├── .github ├── Test Current.settings.json ├── Test Next Major.settings.json ├── Test Next Minor.settings.json ├── AL-Go-Settings.json ├── workflows │ ├── Troubleshooting.yaml │ ├── DeployReferenceDocumentation.yaml │ ├── AddExistingAppOrTestApp.yaml │ ├── IncrementVersionNumber.yaml │ ├── CreateApp.yaml │ ├── CreateTestApp.yaml │ ├── CreatePerformanceTestApp.yaml │ ├── UpdateGitHubGoSystemFiles.yaml │ ├── Current.yaml │ ├── NextMajor.yaml │ ├── NextMinor.yaml │ ├── PullRequestHandler.yaml │ ├── CreateOnlineDevelopmentEnvironment.yaml │ ├── PublishToEnvironment.yaml │ ├── _BuildALGoProject.yaml │ ├── CICD.yaml │ └── CreateRelease.yaml └── RELEASENOTES.copy.md ├── .gitignore ├── .AL-Go ├── settings.json ├── cloudDevEnv.ps1 └── localDevEnv.ps1 ├── LICENSE ├── Discord.code-workspace └── README.md /CODEOWNERS: -------------------------------------------------------------------------------- 1 | @juliandittmann -------------------------------------------------------------------------------- /App/permissionsAnalyzer.json: -------------------------------------------------------------------------------- 1 | {"permissions": "permissions.json", "roles": ["D365 BUS PREMIUM"]} -------------------------------------------------------------------------------- /Demo/permissionsAnalyzer.json: -------------------------------------------------------------------------------- 1 | {"permissions": "permissions.json", "roles": ["D365 BUS PREMIUM"]} -------------------------------------------------------------------------------- /Test/permissionsAnalyzer.json: -------------------------------------------------------------------------------- 1 | {"permissions": "permissions.json", "roles": ["D365 BUS PREMIUM"]} -------------------------------------------------------------------------------- /App/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "waldo.al-extension-pack" 4 | ] 5 | } -------------------------------------------------------------------------------- /Demo/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "waldo.al-extension-pack" 4 | ] 5 | } -------------------------------------------------------------------------------- /Test/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "waldo.al-extension-pack" 4 | ] 5 | } -------------------------------------------------------------------------------- /assets/discord_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juliandittmann/AL.Discord/HEAD/assets/discord_banner.png -------------------------------------------------------------------------------- /App/AppSourceCop.json: -------------------------------------------------------------------------------- 1 | { 2 | "mandatoryPrefix": "jdi Discord ", 3 | "supportedCountries": [ 4 | "US" 5 | ] 6 | } -------------------------------------------------------------------------------- /.github/Test Current.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifact": "////latest", 3 | "cacheImageName": "", 4 | "versioningStrategy": 15 5 | } 6 | -------------------------------------------------------------------------------- /Demo/AppSourceCop.json: -------------------------------------------------------------------------------- 1 | { 2 | "mandatoryPrefix": "jdi Discord Demo", 3 | "supportedCountries": [ 4 | "US" 5 | ] 6 | } -------------------------------------------------------------------------------- /Test/AppSourceCop.json: -------------------------------------------------------------------------------- 1 | { 2 | "mandatoryPrefix": "jdi Discord Test", 3 | "supportedCountries": [ 4 | "US" 5 | ] 6 | } -------------------------------------------------------------------------------- /.github/Test Next Major.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifact": "////nextmajor", 3 | "cacheImageName": "", 4 | "versioningStrategy": 15 5 | } 6 | -------------------------------------------------------------------------------- /.github/Test Next Minor.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifact": "////nextminor", 3 | "cacheImageName": "", 4 | "versioningStrategy": 15 5 | } 6 | -------------------------------------------------------------------------------- /App/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CRS.ObjectNamePrefix": "jdi Discord ", 3 | "CRS.RemovePrefixFromFilename": true, 4 | "al.ruleSetPath": ".codeanalysis/ignoreRuleset.ruleset.json", 5 | } -------------------------------------------------------------------------------- /App/src/Addin/Script/Interface.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Called from BC 3 | * @param {JSON} WidgetBotJObject 4 | */ 5 | function CreateControl(WidgetBotJObject) 6 | { 7 | Widgetbot.show(WidgetBotJObject); 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/Packages/** 2 | */.vscode/** 3 | */.alpackages/** 4 | */.altestrunner/** 5 | */Translations/*.g.xlf 6 | **/**.app 7 | **/**.log 8 | **/**.tmp 9 | !*/.vscode/settings.json 10 | !*/.vscode/extensions.json -------------------------------------------------------------------------------- /Demo/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "al.codeAnalyzers": [], 3 | "CRS.ObjectNamePrefix": "jdi Discord Demo ", 4 | "CRS.RemovePrefixFromFilename": true, 5 | "al.ruleSetPath": ".codeanalysis/ignoreRuleset.ruleset.json", 6 | } -------------------------------------------------------------------------------- /Test/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "al.codeAnalyzers": [], 3 | "CRS.ObjectNamePrefix": "jdi Discord Test ", 4 | "CRS.RemovePrefixFromFilename": true, 5 | "al.ruleSetPath": ".codeanalysis/ignoreRuleset.ruleset.json", 6 | } -------------------------------------------------------------------------------- /Demo/src/Install&Upgrade/Install.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// Discord Demo Install 3 | /// 4 | codeunit 52549 "jdi Discord Demo Install" 5 | { 6 | Subtype = Install; 7 | 8 | trigger OnInstallAppPerCompany() 9 | var 10 | begin 11 | 12 | end; 13 | } -------------------------------------------------------------------------------- /.github/AL-Go-Settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "PTE", 3 | "templateUrl": "https://github.com/microsoft/AL-Go-PTE@main", 4 | "templateSha": "ba4fc723e4c024674baa6a53ef1777402cfbaab0", 5 | "runs-on": "ubuntu-latest", 6 | "CICDPushBranches": [ 7 | "main", 8 | "release/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /App/src/Addin/Script/Utility.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Enter Element Id 3 | * @param {Text} textID 4 | */ 5 | function deleteID(textID) { 6 | while (document.getElementById(textID) != null) { 7 | var ax = document.getElementById(textID); 8 | ax.parentNode.removeChild(ax); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /App/src/Permissions/User.PermissionSet.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// Permission Set for Discord User 3 | /// 4 | permissionset 52500 "jdi Discord User" 5 | { 6 | Caption = 'Discord User'; 7 | Assignable = true; 8 | Permissions = 9 | codeunit "jdi Discord Widgetbot Setup" = X; 10 | } -------------------------------------------------------------------------------- /.AL-Go/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "country": "us", 3 | "alDoc": { 4 | "continuousDeployment": true, 5 | "groupByProject": true 6 | }, 7 | "appFolders": [ 8 | "App" 9 | ], 10 | "testFolders": [ 11 | "Test", 12 | "Demo" 13 | ], 14 | "bcptTestFolders": [], 15 | "repoVersion": "25.1" 16 | } 17 | -------------------------------------------------------------------------------- /Demo/src/Permissions/Basic.PermissionSetExt.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// This permission set extension is used to add the jdi Discord DemoUser permission set to the D365 BASIC permission set. 3 | /// 4 | permissionsetextension 52549 "jdi Discord Demo Basic" extends "D365 BASIC" 5 | { 6 | IncludedPermissionSets = "jdi Discord Demo User"; 7 | } -------------------------------------------------------------------------------- /Demo/src/Permissions/User.PermissionSet.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// This permission set is used to define the jdi Discord DemoUser permission set. 3 | /// 4 | permissionset 52549 "jdi Discord Demo User" 5 | { 6 | Assignable = false; 7 | IncludedPermissionSets = "jdi Discord User"; 8 | Permissions = 9 | page "jdi Discord Demo App" = X; 10 | } -------------------------------------------------------------------------------- /Test/src/Install&Upgrade/Install.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// jdi Discord Test Helper 3 | /// 4 | codeunit 50101 "jdi Discord Test Install" 5 | { 6 | Subtype = Install; 7 | 8 | trigger OnInstallAppPerCompany() 9 | var 10 | TestToolHelper: Codeunit "jdi Discord Test Helper"; 11 | begin 12 | TestToolHelper.Create('DEFAULT', '50100..50199', true); 13 | end; 14 | } -------------------------------------------------------------------------------- /App/.codeanalysis/ignoreRuleset.ruleset.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ignore Ruleset", 3 | "description": "These rules are ignored", 4 | "rules": [ 5 | { 6 | "id": "AS0051", 7 | "action": "Hidden", 8 | "justification": "This is a Template" 9 | }, 10 | { 11 | "id": "AS0084", 12 | "action": "Hidden", 13 | "justification": "Objectrange in Template does not matter" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /Demo/.codeanalysis/ignoreRuleset.ruleset.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ignore Ruleset", 3 | "description": "These rules are ignored", 4 | "rules": [ 5 | { 6 | "id": "AS0051", 7 | "action": "Hidden", 8 | "justification": "This is a Template" 9 | }, 10 | { 11 | "id": "AS0084", 12 | "action": "Hidden", 13 | "justification": "Objectrange in Template does not matter" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /Test/.codeanalysis/ignoreRuleset.ruleset.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ignore Ruleset", 3 | "description": "These rules are ignored", 4 | "rules": [ 5 | { 6 | "id": "AS0051", 7 | "action": "Hidden", 8 | "justification": "This is a Template" 9 | }, 10 | { 11 | "id": "AS0084", 12 | "action": "Hidden", 13 | "justification": "Objectrange in Template does not matter" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /App/src/Addin/Script/Startup.js: -------------------------------------------------------------------------------- 1 | var iframe = window.frameElement; 2 | 3 | iframe.parentElement.style.display = 'flex'; 4 | iframe.parentElement.style.flexDirection = 'column'; 5 | iframe.parentElement.style.flexGrow = '1'; 6 | 7 | iframe.style.removeProperty('height'); 8 | iframe.style.removeProperty('min-height'); 9 | iframe.style.removeProperty('max-height'); 10 | 11 | iframe.style.height = '-webkit-fill-available'; 12 | 13 | var controlAddIn = document.getElementById('controlAddIn'); 14 | 15 | $(document).ready(function () { 16 | $navControlContainer = $("#controlAddIn"); 17 | Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('ControlAddinLoaded', null); 18 | }); -------------------------------------------------------------------------------- /Demo/src/Install&Upgrade/Upgrade.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// Discord Demo Upgrade 3 | /// 4 | codeunit 52550 "jdi Discord Demo Upgrade" 5 | { 6 | Subtype = Upgrade; 7 | 8 | trigger OnCheckPreconditionsPerCompany() 9 | begin 10 | 11 | end; 12 | 13 | trigger OnCheckPreconditionsPerDatabase() 14 | begin 15 | 16 | end; 17 | 18 | trigger OnUpgradePerCompany() 19 | begin 20 | 21 | end; 22 | 23 | trigger OnUpgradePerDatabase() 24 | begin 25 | 26 | end; 27 | 28 | trigger OnValidateUpgradePerCompany() 29 | begin 30 | 31 | end; 32 | 33 | trigger OnValidateUpgradePerDatabase() 34 | begin 35 | 36 | end; 37 | } -------------------------------------------------------------------------------- /Test/src/Install&Upgrade/Upgrade.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// jdi Discord Test Upgrade 3 | /// 4 | codeunit 50102 "jdi Discord Test Upgrade" 5 | { 6 | Subtype = Upgrade; 7 | 8 | trigger OnCheckPreconditionsPerCompany() 9 | begin 10 | 11 | end; 12 | 13 | trigger OnCheckPreconditionsPerDatabase() 14 | begin 15 | 16 | end; 17 | 18 | trigger OnUpgradePerCompany() 19 | begin 20 | 21 | end; 22 | 23 | trigger OnUpgradePerDatabase() 24 | begin 25 | 26 | end; 27 | 28 | trigger OnValidateUpgradePerCompany() 29 | begin 30 | 31 | end; 32 | 33 | trigger OnValidateUpgradePerDatabase() 34 | begin 35 | 36 | end; 37 | } -------------------------------------------------------------------------------- /App/src/Addin/Widgetbot.ControlAddin.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// WidgetBot Control Addin 3 | /// 4 | controladdin "jdi Discord Widgetbot" 5 | { 6 | VerticalStretch = true; 7 | VerticalShrink = true; 8 | HorizontalStretch = true; 9 | HorizontalShrink = true; 10 | Scripts = 11 | 'https://code.jquery.com/jquery-3.3.1.min.js', 12 | './src/Addin/Script/Widgetbot.js', 13 | './src/Addin/Script/Interface.js', 14 | './src/Addin/Script/Utility.js'; 15 | 16 | StartupScript = 17 | './src/Addin/Script/Startup.js'; 18 | 19 | event ControlAddinLoaded(); 20 | 21 | /// 22 | /// Create Control 23 | /// 24 | /// 25 | procedure CreateControl(WidgetBotSetupJObject: JsonObject); 26 | } -------------------------------------------------------------------------------- /App/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c9841816-11a6-46d9-89ab-9ea657a4a92d", 3 | "name": "Discord", 4 | "publisher": "Julian Dittmann", 5 | "brief": "", 6 | "description": "", 7 | "version": "25.1.0.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "https://github.com/juliandittmann/AL.Discord", 12 | "logo": "", 13 | "dependencies": [], 14 | "screenshots": [], 15 | "platform": "19.0.0.0", 16 | "application": "19.0.0.0", 17 | "runtime": "8.1", 18 | "target": "Cloud", 19 | "resourceExposurePolicy": { 20 | "allowDebugging": true, 21 | "allowDownloadingSource": true, 22 | "includeSourceInSymbolFile": true 23 | }, 24 | "idRanges": [ 25 | { 26 | "from": 52500, 27 | "to": 52549 28 | } 29 | ], 30 | "contextSensitiveHelpUrl": "https://example.com/help/", 31 | "features": [ 32 | "TranslationFile" 33 | ], 34 | "supportedLocales": [ 35 | "en-US" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /App/src/Addin/Script/Widgetbot.js: -------------------------------------------------------------------------------- 1 | var Widgetbot; 2 | (function (Widgetbot) { 3 | //Config for ElementIds 4 | var Config = { 5 | Widgetbot: "widgetbot" 6 | }; 7 | 8 | //Show Widgetbot 9 | Widgetbot.show = function (Setup) { 10 | var Html = Widgetbot.getHtml(Setup); 11 | $navControlContainer.append(Html); 12 | } 13 | 14 | //Remove Widgetbot 15 | Widgetbot.remove = function () { 16 | deleteID(Config.Widgetbot); 17 | } 18 | 19 | //Get HTML-Content for "Widgetbot" 20 | Widgetbot.getHtml = function (Setup) { 21 | var Html = ''; 22 | Html += ''; 23 | Html += ''; 24 | return Html; 25 | } 26 | })(Widgetbot || (Widgetbot = {})); 27 | 28 | -------------------------------------------------------------------------------- /Demo/src/App.Page.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// Discord Demo App 3 | /// 4 | page 52549 "jdi Discord Demo App" 5 | { 6 | PageType = Card; 7 | ApplicationArea = All; 8 | UsageCategory = Tasks; 9 | 10 | Caption = 'Discord'; 11 | 12 | layout 13 | { 14 | area(Content) 15 | { 16 | usercontrol("WidgetBot"; "jdi Discord Widgetbot") 17 | { 18 | ApplicationArea = all; 19 | 20 | trigger ControlAddinLoaded() 21 | var 22 | WidgetBotSetup: Codeunit "jdi Discord Widgetbot Setup"; 23 | WidgetBotSetupJObject: JsonObject; 24 | begin 25 | WidgetBotSetupJObject := WidgetBotSetup.CreateWidgetBotSetup('930840323440119858', '930840323440119861'); 26 | CurrPage.WidgetBot.CreateControl(WidgetBotSetupJObject); 27 | end; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /.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: pwsh 18 | 19 | env: 20 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 21 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 22 | 23 | jobs: 24 | Troubleshooting: 25 | runs-on: [ ubuntu-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@v6.3 34 | with: 35 | shell: pwsh 36 | gitHubSecrets: ${{ toJson(secrets) }} 37 | displayNameOfSecrets: ${{ github.event.inputs.displayNameOfSecrets }} 38 | -------------------------------------------------------------------------------- /Demo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "deadcc42-4874-4741-b014-47d8853db8b4", 3 | "name": "Discord Demo", 4 | "publisher": "Julian Dittmann", 5 | "brief": "Discord Demo App", 6 | "description": "Discord Demo App", 7 | "version": "25.1.0.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "https://github.com/juliandittmann/AL.Discord", 12 | "logo": "", 13 | "dependencies": [ 14 | { 15 | "name": "Discord", 16 | "publisher": "Julian Dittmann", 17 | "version": "25.1.0.0", 18 | "id": "c9841816-11a6-46d9-89ab-9ea657a4a92d" 19 | } 20 | ], 21 | "screenshots": [], 22 | "application": "19.0.0.0", 23 | "platform": "19.0.0.0", 24 | "runtime": "8.1", 25 | "target": "Cloud", 26 | "resourceExposurePolicy": { 27 | "allowDebugging": true, 28 | "allowDownloadingSource": true, 29 | "includeSourceInSymbolFile": true 30 | }, 31 | "idRanges": [ 32 | { 33 | "from": 52549, 34 | "to": 52599 35 | } 36 | ], 37 | "features": [ 38 | "TranslationFile" 39 | ], 40 | "supportedLocales": [ 41 | "en-US" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 juliandittmann 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 | -------------------------------------------------------------------------------- /App/src/WidgetbotSetup.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// WidgetBot Setup Codeunit 3 | /// 4 | codeunit 52500 "jdi Discord Widgetbot Setup" 5 | { 6 | /// 7 | /// Create WidgetBot Setup JSON Object 8 | /// 9 | /// 10 | /// 11 | /// 12 | procedure CreateWidgetBotSetup(ServerId: Text; ChannelId: Text): JsonObject 13 | begin 14 | exit(CreateWidgetBotSetup(ServerId, ChannelId, '100%', '98%')); 15 | end; 16 | 17 | /// 18 | /// Create WidgetBot Setup JSON Object 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | procedure CreateWidgetBotSetup(ServerId: Text; ChannelId: Text; Height: Text; Width: Text): JsonObject 26 | var 27 | WidgetBotJObject: JsonObject; 28 | begin 29 | WidgetBotJObject.Add('serverid', ServerId); 30 | WidgetBotJObject.Add('channelid', ChannelId); 31 | WidgetBotJObject.Add('height', Height); 32 | WidgetBotJObject.Add('width', Width); 33 | exit(WidgetBotJObject); 34 | end; 35 | } -------------------------------------------------------------------------------- /Discord.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "App" 5 | }, 6 | { 7 | "path": "Demo" 8 | }, 9 | { 10 | "path": "Test" 11 | } 12 | ], 13 | "settings": { 14 | "[al]": { 15 | "editor.defaultFormatter": "ms-dynamics-smb.al" 16 | }, 17 | "al.enableCodeActions": true, 18 | "al.codeAnalyzers": [ 19 | "${AppSourceCop}", 20 | "${CodeCop}", 21 | "${UICop}" 22 | ], 23 | "al.enableCodeAnalysis": true, 24 | "al.compilationOptions": { 25 | "parallel": true 26 | }, 27 | "al.incrementalBuild": true, 28 | 29 | "CRS.OnSaveAlFileAction": "Rename", 30 | "CRS.FileNamePattern": "..al", 31 | "CRS.FileNamePatternExtensions": "..al", 32 | "CRS.FileNamePatternPageCustomizations": "..al" 33 | }, 34 | "extensions": { 35 | "recommendations": [ 36 | "ms-dynamics-smb.al", 37 | "waldo.al-extension-pack", 38 | "martonsagi.al-object-designer", 39 | "jamespearson.al-test-runner", 40 | "bartpermentier.al-toolbox", 41 | "davidfeldhoff.al-codeactions" 42 | ] 43 | } 44 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![ CI/CD](https://github.com/juliandittmann/AL.Discord/actions/workflows/CICD.yaml/badge.svg)](https://github.com/juliandittmann/AL.Discord/actions/workflows/CICD.yaml) 2 | 3 | [![license](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE) 4 | 5 | ![Discord Logo](assets/discord_banner.png) 6 | 7 | # Discord for Dynamics 365 Business Central 8 | 9 | Integrate Discord chat features in Dynamics 365 Business Central with [widgetbot](https://widgetbot.io/). 10 | 11 | ## Setup Discord Server 12 | 13 | Do the following steps: 14 | 15 | 1. Follow the [tutorial](https://docs.widgetbot.io/tutorial/) 16 | 2. Recieve the serverid and a channelid 17 | 18 | ## Connect to the Discord server from Dynamics 365 Business Central 19 | 20 | Use the provided control addin. 21 | 22 | You can find an [example](https://github.com/juliandittmann/AL.Discord/blob/main/Demo/src/App.Page.al) in the demo app folder 23 | 24 | ``` 25 | usercontrol("WidgetBot"; "jdi Discord Widgetbot") 26 | { 27 | ApplicationArea = all; 28 | 29 | trigger ControlAddinLoaded() 30 | var 31 | WidgetBotSetup: Codeunit "jdi Discord Widgetbot Setup"; 32 | WidgetBotSetupJObject: JsonObject; 33 | begin 34 | WidgetBotSetupJObject := WidgetBotSetup.CreateWidgetBotSetup('', ''); 35 | CurrPage.WidgetBot.CreateControl(WidgetBotSetupJObject); 36 | end; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /Test/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "3b110653-d432-41b0-ad8d-93b7a907d5ea", 3 | "name": "Discord Test", 4 | "publisher": "Julian Dittmann", 5 | "brief": "Discord Test App", 6 | "description": "Discord Test App", 7 | "version": "25.1.0.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "https://github.com/juliandittmann/AL.Discord", 12 | "logo": "", 13 | "dependencies": [ 14 | { 15 | "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", 16 | "publisher": "Microsoft", 17 | "name": "Library Assert", 18 | "version": "19.0.0.0" 19 | }, 20 | { 21 | "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", 22 | "publisher": "Microsoft", 23 | "name": "Any", 24 | "version": "19.0.0.0" 25 | }, 26 | { 27 | "id": "9856ae4f-d1a7-46ef-89bb-6ef056398228", 28 | "publisher": "Microsoft", 29 | "name": "System Application Test Library", 30 | "version": "19.0.0.0" 31 | }, 32 | { 33 | "id": "5d86850b-0d76-4eca-bd7b-951ad998e997", 34 | "publisher": "Microsoft", 35 | "name": "Tests-TestLibraries", 36 | "version": "19.0.0.0" 37 | }, 38 | { 39 | "name": "Test Runner", 40 | "publisher": "Microsoft", 41 | "version": "19.0.0.0", 42 | "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf" 43 | }, 44 | { 45 | "name": "Discord", 46 | "publisher": "Julian Dittmann", 47 | "version": "25.1.0.0", 48 | "id": "c9841816-11a6-46d9-89ab-9ea657a4a92d" 49 | } 50 | ], 51 | "screenshots": [], 52 | "application": "19.0.0.0", 53 | "platform": "19.0.0.0", 54 | "runtime": "8.1", 55 | "target": "Cloud", 56 | "resourceExposurePolicy": { 57 | "allowDebugging": true, 58 | "allowDownloadingSource": true, 59 | "includeSourceInSymbolFile": true 60 | }, 61 | "idRanges": [ 62 | { 63 | "from": 50100, 64 | "to": 50199 65 | } 66 | ], 67 | "features": [ 68 | "TranslationFile" 69 | ], 70 | "supportedLocales": [ 71 | "en-US" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /Test/test/Setup.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// jdi Discord Test Setup 3 | /// 4 | codeunit 50103 "jdi Discord Test Setup" 5 | { 6 | Subtype = Test; 7 | TestPermissions = Disabled; 8 | 9 | [Test] 10 | procedure TestWidgetBotSetupCreation() 11 | var 12 | WidgetbotSetup: Codeunit "jdi Discord Widgetbot Setup"; 13 | WidgetBotSetupJObject: JsonObject; 14 | 15 | ChannelId: Text; 16 | ServerId: Text; 17 | 18 | ServerIdJToken: JsonToken; 19 | ChannelIdJToken: JsonToken; 20 | HeightJToken: JsonToken; 21 | WidthJToken: JsonToken; 22 | begin 23 | //Set Basic Permission 24 | LibraryLowerPermissions.SetO365Basic(); 25 | 26 | //Create Test Data 27 | ServerId := Any.AlphanumericText(50); 28 | ChannelId := Any.AlphanumericText(50); 29 | 30 | //Create WidgetBot Setup JsonObject 31 | WidgetBotSetupJObject := WidgetbotSetup.CreateWidgetBotSetup(ServerId, ChannelId); 32 | 33 | //Assert WidgetBot Setup JsonObject is complete 34 | Assert.IsTrue(WidgetBotSetupJObject.Get('serverid', ServerIdJToken), 'serverid token should exist.'); 35 | Assert.IsTrue(WidgetBotSetupJObject.Get('channelid', ChannelIdJToken), 'channelid token should exist.'); 36 | Assert.IsTrue(WidgetBotSetupJObject.Get('height', HeightJToken), 'heigth token should exist.'); 37 | Assert.IsTrue(WidgetBotSetupJObject.Get('width', WidthJToken), 'serverid token should exist.'); 38 | 39 | //Assert WidgetBot Setup JsonObject values are correcty set 40 | Assert.AreEqual(ServerId, ServerIdJToken.AsValue().AsText(), 'serverids should be equal.'); 41 | Assert.AreEqual(ChannelId, ChannelIdJToken.AsValue().AsText(), 'channelids should be equal.'); 42 | Assert.AreEqual('100%', HeightJToken.AsValue().AsText(), 'height should be equal.'); 43 | Assert.AreEqual('98%', WidthJToken.AsValue().AsText(), 'width should be equal.'); 44 | end; 45 | 46 | var 47 | Assert: Codeunit Assert; 48 | Any: Codeunit Any; 49 | LibraryLowerPermissions: Codeunit "Library - Lower Permissions"; 50 | 51 | } -------------------------------------------------------------------------------- /.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: pwsh 15 | 16 | env: 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | DeployALDoc: 22 | runs-on: [ ubuntu-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@v6.3 34 | with: 35 | shell: pwsh 36 | 37 | - name: Read settings 38 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 39 | with: 40 | shell: pwsh 41 | 42 | - name: Determine Deployment Environments 43 | id: DetermineDeploymentEnvironments 44 | uses: microsoft/AL-Go-Actions/DetermineDeploymentEnvironments@v6.3 45 | env: 46 | GITHUB_TOKEN: ${{ github.token }} 47 | with: 48 | shell: pwsh 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@v6.3 58 | with: 59 | shell: pwsh 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@v6.3 75 | env: 76 | GITHUB_TOKEN: ${{ github.token }} 77 | with: 78 | shell: pwsh 79 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 80 | currentJobContext: ${{ toJson(job) }} 81 | -------------------------------------------------------------------------------- /.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: pwsh 33 | 34 | env: 35 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 36 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 37 | 38 | jobs: 39 | AddExistingAppOrTestApp: 40 | needs: [ ] 41 | runs-on: [ ubuntu-latest ] 42 | steps: 43 | - name: Dump Workflow Information 44 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 45 | with: 46 | shell: pwsh 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@v6.3 54 | with: 55 | shell: pwsh 56 | 57 | - name: Read settings 58 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 59 | with: 60 | shell: pwsh 61 | 62 | - name: Read secrets 63 | id: ReadSecrets 64 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 65 | with: 66 | shell: pwsh 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@v6.3 73 | with: 74 | shell: pwsh 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@v6.3 83 | env: 84 | GITHUB_TOKEN: ${{ github.token }} 85 | with: 86 | shell: pwsh 87 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 88 | currentJobContext: ${{ toJson(job) }} 89 | -------------------------------------------------------------------------------- /Test/lib/Helper.Codeunit.al: -------------------------------------------------------------------------------- 1 | /// 2 | /// This codeunit is used to create a test suite and add test methods to it. 3 | /// 4 | codeunit 50100 "jdi Discord Test Helper" 5 | { 6 | /// 7 | /// This function is used to create a test suite and add test methods to it. 8 | /// 9 | /// 10 | /// 11 | /// 12 | procedure Create(TestSuiteName: code[10]; TestCodeunitFilter: Text; EmptyTestSuite: Boolean) 13 | var 14 | ALTestSuite: Record "AL Test Suite"; 15 | TestMethodLine: Record "Test Method Line"; 16 | TempAllObjWithCaption: Record AllObjWithCaption temporary; 17 | 18 | TestSuiteMgt: Codeunit "Test Suite Mgt."; 19 | begin 20 | TryInsertTestSuite(TestSuiteName, ALTestSuite); 21 | 22 | TestMethodLine.Setrange("Test Suite", TestSuiteName); 23 | if EmptyTestSuite then 24 | TestMethodLine.DeleteAll(true); 25 | 26 | if GetTestCodeunits(TestCodeunitFilter, TempAllObjWithCaption) then 27 | TestSuiteMgt.GetTestMethods(ALTestSuite, TempAllObjWithCaption); 28 | 29 | end; 30 | 31 | /// 32 | /// This function is used to try to insert a test suite. 33 | /// 34 | /// 35 | /// 36 | local procedure TryInsertTestSuite(TestSuiteName: code[10]; var ALTestSuite: Record "AL Test Suite") 37 | begin 38 | if ALTestSuite.Get(TestSuiteName) then 39 | exit; 40 | 41 | ALTestSuite.Init(); 42 | ALTestSuite.Validate(Name, TestSuiteName); 43 | ALTestSuite.Validate(Description, TestSuiteName); 44 | ALTestSuite.Insert(true); 45 | end; 46 | 47 | /// 48 | /// This function is used to get test codeunits. 49 | /// 50 | /// 51 | /// 52 | /// 53 | local procedure GetTestCodeunits(TestCodeunitFilter: Text; VAR ToAllObjWithCaption: Record AllObjWithCaption): Boolean; 54 | var 55 | FromAllObjWithCaption: Record AllObjWithCaption; 56 | begin 57 | FromAllObjWithCaption.Setrange("Object Type", ToAllObjWithCaption."Object Type"::Codeunit); 58 | FromAllObjWithCaption.SetFilter("Object ID", TestCodeunitFilter); 59 | FromAllObjWithCaption.Setrange("Object Subtype", 'Test'); 60 | if FromAllObjWithCaption.Find('-') then 61 | repeat 62 | ToAllObjWithCaption := FromAllObjWithCaption; 63 | ToAllObjWithCaption.Insert(); 64 | until FromAllObjWithCaption.Next() = 0; 65 | 66 | exit(ToAllObjWithCaption.Find('-')); 67 | end; 68 | } -------------------------------------------------------------------------------- /.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: pwsh 32 | 33 | env: 34 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 35 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 36 | 37 | jobs: 38 | IncrementVersionNumber: 39 | needs: [ ] 40 | runs-on: [ ubuntu-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@v6.3 49 | with: 50 | shell: pwsh 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@v6.3 58 | with: 59 | shell: pwsh 60 | 61 | - name: Read settings 62 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 63 | with: 64 | shell: pwsh 65 | 66 | - name: Read secrets 67 | id: ReadSecrets 68 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 69 | with: 70 | shell: pwsh 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@v6.3 77 | with: 78 | shell: pwsh 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@v6.3 88 | env: 89 | GITHUB_TOKEN: ${{ github.token }} 90 | with: 91 | shell: pwsh 92 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 93 | currentJobContext: ${{ toJson(job) }} 94 | -------------------------------------------------------------------------------- /.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: pwsh 43 | 44 | env: 45 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 46 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 47 | 48 | jobs: 49 | CreateApp: 50 | needs: [ ] 51 | runs-on: [ ubuntu-latest ] 52 | steps: 53 | - name: Dump Workflow Information 54 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 55 | with: 56 | shell: pwsh 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@v6.3 64 | with: 65 | shell: pwsh 66 | 67 | - name: Read settings 68 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 69 | with: 70 | shell: pwsh 71 | get: type 72 | 73 | - name: Read secrets 74 | id: ReadSecrets 75 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 76 | with: 77 | shell: pwsh 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@v6.3 84 | with: 85 | shell: pwsh 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@v6.3 98 | env: 99 | GITHUB_TOKEN: ${{ github.token }} 100 | with: 101 | shell: pwsh 102 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 103 | currentJobContext: ${{ toJson(job) }} 104 | -------------------------------------------------------------------------------- /.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: pwsh 45 | 46 | env: 47 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 48 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 49 | 50 | jobs: 51 | CreateTestApp: 52 | needs: [ ] 53 | runs-on: [ ubuntu-latest ] 54 | steps: 55 | - name: Dump Workflow Information 56 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 57 | with: 58 | shell: pwsh 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@v6.3 66 | with: 67 | shell: pwsh 68 | 69 | - name: Read settings 70 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 71 | with: 72 | shell: pwsh 73 | 74 | - name: Read secrets 75 | id: ReadSecrets 76 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 77 | with: 78 | shell: pwsh 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@v6.3 85 | with: 86 | shell: pwsh 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@v6.3 99 | env: 100 | GITHUB_TOKEN: ${{ github.token }} 101 | with: 102 | shell: pwsh 103 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 104 | currentJobContext: ${{ toJson(job) }} 105 | -------------------------------------------------------------------------------- /.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: pwsh 49 | 50 | env: 51 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 52 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 53 | 54 | jobs: 55 | CreatePerformanceTestApp: 56 | needs: [ ] 57 | runs-on: [ ubuntu-latest ] 58 | steps: 59 | - name: Dump Workflow Information 60 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 61 | with: 62 | shell: pwsh 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@v6.3 70 | with: 71 | shell: pwsh 72 | 73 | - name: Read settings 74 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 75 | with: 76 | shell: pwsh 77 | 78 | - name: Read secrets 79 | id: ReadSecrets 80 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 81 | with: 82 | shell: pwsh 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@v6.3 89 | with: 90 | shell: pwsh 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@v6.3 104 | env: 105 | GITHUB_TOKEN: ${{ github.token }} 106 | with: 107 | shell: pwsh 108 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 109 | currentJobContext: ${{ toJson(job) }} 110 | -------------------------------------------------------------------------------- /.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-PTE@main) 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 | 19 | permissions: 20 | actions: read 21 | contents: read 22 | id-token: write 23 | 24 | defaults: 25 | run: 26 | shell: pwsh 27 | 28 | env: 29 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 30 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 31 | 32 | jobs: 33 | UpdateALGoSystemFiles: 34 | name: 'Update AL-Go System Files' 35 | needs: [ ] 36 | runs-on: [ ubuntu-latest ] 37 | steps: 38 | - name: Dump Workflow Information 39 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 40 | with: 41 | shell: pwsh 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@v6.3 49 | with: 50 | shell: pwsh 51 | 52 | - name: Read settings 53 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 54 | with: 55 | shell: pwsh 56 | get: templateUrl 57 | 58 | - name: Read secrets 59 | id: ReadSecrets 60 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 61 | with: 62 | shell: pwsh 63 | gitHubSecrets: ${{ toJson(secrets) }} 64 | getSecrets: 'ghTokenWorkflow' 65 | 66 | - name: Override templateUrl 67 | env: 68 | templateUrl: ${{ github.event.inputs.templateUrl }} 69 | run: | 70 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 71 | $templateUrl = $ENV:templateUrl 72 | if ($templateUrl) { 73 | Write-Host "Using Template Url: $templateUrl" 74 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "templateUrl=$templateUrl" 75 | } 76 | 77 | - name: Calculate Input 78 | env: 79 | directCommit: '${{ github.event.inputs.directCommit }}' 80 | downloadLatest: ${{ github.event.inputs.downloadLatest }} 81 | eventName: ${{ github.event_name }} 82 | run: | 83 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 84 | $directCommit = $ENV:directCommit 85 | $downloadLatest = $ENV:downloadLatest 86 | Write-Host $ENV:eventName 87 | if ($ENV:eventName -eq 'schedule') { 88 | Write-Host "Running Update AL-Go System Files on a schedule. Setting DirectCommit and DownloadLatest to true" 89 | $directCommit = 'true' 90 | $downloadLatest = 'true' 91 | } 92 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "directCommit=$directCommit" 93 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "downloadLatest=$downloadLatest" 94 | 95 | - name: Update AL-Go system files 96 | uses: microsoft/AL-Go-Actions/CheckForUpdates@v6.3 97 | with: 98 | shell: pwsh 99 | token: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).ghTokenWorkflow }} 100 | downloadLatest: ${{ env.downloadLatest }} 101 | update: 'Y' 102 | templateUrl: ${{ env.templateUrl }} 103 | directCommit: ${{ env.directCommit }} 104 | 105 | - name: Finalize the workflow 106 | if: always() 107 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v6.3 108 | env: 109 | GITHUB_TOKEN: ${{ github.token }} 110 | with: 111 | shell: pwsh 112 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 113 | currentJobContext: ${{ toJson(job) }} 114 | -------------------------------------------------------------------------------- /.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/v6.3/Github-Helper.psm1' -folder $tmpFolder 46 | $ALGoHelperPath = DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v6.3/AL-Go-Helper.ps1' -folder $tmpFolder 47 | DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v6.3/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 | -------------------------------------------------------------------------------- /.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: pwsh 14 | 15 | env: 16 | workflowDepth: 1 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | Initialization: 22 | needs: [ ] 23 | runs-on: [ ubuntu-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@v6.3 34 | with: 35 | shell: pwsh 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@v6.3 45 | with: 46 | shell: pwsh 47 | 48 | - name: Read settings 49 | id: ReadSettings 50 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 51 | with: 52 | shell: pwsh 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@v6.3 59 | with: 60 | shell: pwsh 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@v6.3 81 | with: 82 | shell: pwsh 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: [ ubuntu-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@v6.3 117 | env: 118 | GITHUB_TOKEN: ${{ github.token }} 119 | with: 120 | shell: pwsh 121 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 122 | currentJobContext: ${{ toJson(job) }} 123 | -------------------------------------------------------------------------------- /.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: pwsh 14 | 15 | env: 16 | workflowDepth: 1 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | Initialization: 22 | needs: [ ] 23 | runs-on: [ ubuntu-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@v6.3 34 | with: 35 | shell: pwsh 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@v6.3 45 | with: 46 | shell: pwsh 47 | 48 | - name: Read settings 49 | id: ReadSettings 50 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 51 | with: 52 | shell: pwsh 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@v6.3 59 | with: 60 | shell: pwsh 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@v6.3 81 | with: 82 | shell: pwsh 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: [ ubuntu-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@v6.3 117 | env: 118 | GITHUB_TOKEN: ${{ github.token }} 119 | with: 120 | shell: pwsh 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: pwsh 14 | 15 | env: 16 | workflowDepth: 1 17 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 18 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 19 | 20 | jobs: 21 | Initialization: 22 | needs: [ ] 23 | runs-on: [ ubuntu-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@v6.3 34 | with: 35 | shell: pwsh 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@v6.3 45 | with: 46 | shell: pwsh 47 | 48 | - name: Read settings 49 | id: ReadSettings 50 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 51 | with: 52 | shell: pwsh 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@v6.3 59 | with: 60 | shell: pwsh 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@v6.3 81 | with: 82 | shell: pwsh 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: [ ubuntu-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@v6.3 117 | env: 118 | GITHUB_TOKEN: ${{ github.token }} 119 | with: 120 | shell: pwsh 121 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 122 | currentJobContext: ${{ toJson(job) }} 123 | -------------------------------------------------------------------------------- /.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: pwsh 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@v6.3 32 | 33 | Initialization: 34 | needs: [ PregateCheck ] 35 | if: (!failure() && !cancelled()) 36 | runs-on: [ ubuntu-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 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 43 | artifactsRetentionDays: ${{ steps.DetermineWorkflowDepth.outputs.ArtifactsRetentionDays }} 44 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 45 | steps: 46 | - name: Dump Workflow Information 47 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 48 | with: 49 | shell: pwsh 50 | 51 | - name: Checkout 52 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 53 | with: 54 | lfs: true 55 | ref: ${{ github.event_name == 'pull_request' && github.sha || format('refs/pull/{0}/merge', github.event.pull_request.number) }} 56 | 57 | - name: Initialize the workflow 58 | id: init 59 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v6.3 60 | with: 61 | shell: pwsh 62 | 63 | - name: Read settings 64 | id: ReadSettings 65 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 66 | with: 67 | shell: pwsh 68 | get: shortLivedArtifactsRetentionDays 69 | 70 | - name: Determine Workflow Depth 71 | id: DetermineWorkflowDepth 72 | run: | 73 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 74 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "ArtifactsRetentionDays=$($env:shortLivedArtifactsRetentionDays)" 75 | 76 | - name: Determine Projects To Build 77 | id: determineProjectsToBuild 78 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v6.3 79 | with: 80 | shell: pwsh 81 | maxBuildDepth: ${{ env.workflowDepth }} 82 | 83 | Build: 84 | needs: [ Initialization ] 85 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 86 | strategy: 87 | matrix: 88 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 89 | fail-fast: false 90 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 91 | uses: ./.github/workflows/_BuildALGoProject.yaml 92 | secrets: inherit 93 | with: 94 | shell: ${{ matrix.githubRunnerShell }} 95 | runsOn: ${{ matrix.githubRunner }} 96 | checkoutRef: ${{ github.event_name == 'pull_request' && github.sha || format('refs/pull/{0}/merge', github.event.pull_request.number) }} 97 | project: ${{ matrix.project }} 98 | projectName: ${{ matrix.projectName }} 99 | buildMode: ${{ matrix.buildMode }} 100 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 101 | baselineWorkflowRunId: ${{ needs.Initialization.outputs.baselineWorkflowRunId }} 102 | secrets: 'licenseFileUrl,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 103 | artifactsRetentionDays: ${{ fromJson(needs.Initialization.outputs.artifactsRetentionDays) }} 104 | artifactsNameSuffix: 'PR${{ github.event.number }}' 105 | 106 | StatusCheck: 107 | needs: [ Initialization, Build ] 108 | if: (!cancelled()) 109 | runs-on: [ ubuntu-latest ] 110 | name: Pull Request Status Check 111 | steps: 112 | - name: Pull Request Status Check 113 | id: PullRequestStatusCheck 114 | uses: microsoft/AL-Go-Actions/PullRequestStatusCheck@v6.3 115 | env: 116 | GITHUB_TOKEN: ${{ github.token }} 117 | with: 118 | shell: pwsh 119 | 120 | - name: Finalize the workflow 121 | id: PostProcess 122 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v6.3 123 | if: success() || failure() 124 | env: 125 | GITHUB_TOKEN: ${{ github.token }} 126 | with: 127 | shell: pwsh 128 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 129 | currentJobContext: ${{ toJson(job) }} 130 | -------------------------------------------------------------------------------- /.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/v6.3/Github-Helper.psm1' -folder $tmpFolder 50 | $ALGoHelperPath = DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v6.3/AL-Go-Helper.ps1' -folder $tmpFolder 51 | DownloadHelperFile -url 'https://raw.githubusercontent.com/microsoft/AL-Go-Actions/v6.3/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 | -------------------------------------------------------------------------------- /.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: pwsh 37 | 38 | env: 39 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 40 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 41 | 42 | jobs: 43 | Initialization: 44 | needs: [ ] 45 | runs-on: [ ubuntu-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@v6.3 54 | with: 55 | shell: pwsh 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@v6.3 63 | with: 64 | shell: pwsh 65 | 66 | - name: Read settings 67 | id: ReadSettings 68 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 69 | with: 70 | shell: pwsh 71 | 72 | - name: Read secrets 73 | id: ReadSecrets 74 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 75 | with: 76 | shell: pwsh 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/v6.3/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@v6.3 116 | with: 117 | shell: pwsh 118 | 119 | - name: Read secrets 120 | id: ReadSecrets 121 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 122 | with: 123 | shell: pwsh 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@v6.3 141 | with: 142 | shell: pwsh 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@v6.3 153 | env: 154 | GITHUB_TOKEN: ${{ github.token }} 155 | with: 156 | shell: pwsh 157 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 158 | currentJobContext: ${{ toJson(job) }} 159 | -------------------------------------------------------------------------------- /.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 or version number) 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: pwsh 22 | 23 | env: 24 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 25 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 26 | 27 | jobs: 28 | Initialization: 29 | needs: [ ] 30 | runs-on: [ ubuntu-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@v6.3 40 | with: 41 | shell: pwsh 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@v6.3 49 | with: 50 | shell: pwsh 51 | 52 | - name: Read settings 53 | id: ReadSettings 54 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 55 | with: 56 | shell: pwsh 57 | 58 | - name: Determine Deployment Environments 59 | id: DetermineDeploymentEnvironments 60 | uses: microsoft/AL-Go-Actions/DetermineDeploymentEnvironments@v6.3 61 | env: 62 | GITHUB_TOKEN: ${{ github.token }} 63 | with: 64 | shell: pwsh 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@v6.3 79 | if: steps.DetermineDeploymentEnvironments.outputs.UnknownEnvironment == 1 80 | with: 81 | shell: pwsh 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/v6.3/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@v6.3 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@v6.3 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@v6.3 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@v6.3 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 | 176 | - name: Deploy to Power Platform 177 | if: env.type == 'PTE' && env.powerPlatformSolutionFolder != '' 178 | uses: microsoft/AL-Go-Actions/DeployPowerPlatform@v6.3 179 | env: 180 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 181 | with: 182 | shell: ${{ matrix.shell }} 183 | environmentName: ${{ matrix.environment }} 184 | artifactsFolder: '.artifacts' 185 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 186 | 187 | PostProcess: 188 | needs: [ Initialization, Deploy ] 189 | if: always() 190 | runs-on: [ ubuntu-latest ] 191 | steps: 192 | - name: Checkout 193 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 194 | 195 | - name: Finalize the workflow 196 | id: PostProcess 197 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v6.3 198 | env: 199 | GITHUB_TOKEN: ${{ github.token }} 200 | with: 201 | shell: pwsh 202 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 203 | currentJobContext: ${{ toJson(job) }} 204 | -------------------------------------------------------------------------------- /.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 | projectDependenciesJson: 31 | description: Dependencies of the built project in compressed Json format 32 | required: false 33 | default: '{}' 34 | type: string 35 | buildMode: 36 | description: Build mode used when building the artifacts 37 | required: true 38 | type: string 39 | baselineWorkflowRunId: 40 | 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 41 | required: false 42 | default: '0' 43 | type: string 44 | secrets: 45 | description: A comma-separated string with the names of the secrets, required for the workflow. 46 | required: false 47 | default: '' 48 | type: string 49 | artifactsRetentionDays: 50 | description: Number of days to keep the artifacts 51 | type: number 52 | default: 0 53 | artifactsNameSuffix: 54 | description: Suffix to add to the artifacts names 55 | required: false 56 | default: '' 57 | type: string 58 | signArtifacts: 59 | description: Flag indicating whether the apps should be signed 60 | type: boolean 61 | default: false 62 | useArtifactCache: 63 | description: Flag determining whether to use the Artifacts Cache 64 | type: boolean 65 | default: false 66 | 67 | permissions: 68 | actions: read 69 | contents: read 70 | id-token: write 71 | 72 | env: 73 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 74 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 75 | 76 | jobs: 77 | BuildALGoProject: 78 | needs: [ ] 79 | runs-on: ${{ fromJson(inputs.runsOn) }} 80 | defaults: 81 | run: 82 | shell: ${{ inputs.shell }} 83 | name: ${{ inputs.projectName }} (${{ inputs.buildMode }}) 84 | steps: 85 | - name: Checkout 86 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 87 | with: 88 | ref: ${{ inputs.checkoutRef }} 89 | lfs: true 90 | 91 | - name: Read settings 92 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 93 | with: 94 | shell: ${{ inputs.shell }} 95 | project: ${{ inputs.project }} 96 | buildMode: ${{ inputs.buildMode }} 97 | get: useCompilerFolder,keyVaultCodesignCertificateName,doNotSignApps,doNotRunTests,artifact,generateDependencyArtifact,trustedSigning,useGitSubmodules 98 | 99 | - name: Read secrets 100 | id: ReadSecrets 101 | if: github.event_name != 'pull_request' 102 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 103 | with: 104 | shell: ${{ inputs.shell }} 105 | gitHubSecrets: ${{ toJson(secrets) }} 106 | getSecrets: '${{ inputs.secrets }},appDependencySecrets,AZURE_CREDENTIALS,-gitSubmodulesToken' 107 | 108 | - name: Checkout Submodules 109 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 110 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 111 | with: 112 | ref: ${{ inputs.checkoutRef }} 113 | lfs: true 114 | submodules: ${{ env.useGitSubmodules }} 115 | token: '${{ fromJson(steps.ReadSecrets.outputs.Secrets).gitSubmodulesToken }}' 116 | 117 | - name: Determine ArtifactUrl 118 | uses: microsoft/AL-Go-Actions/DetermineArtifactUrl@v6.3 119 | id: determineArtifactUrl 120 | with: 121 | shell: ${{ inputs.shell }} 122 | project: ${{ inputs.project }} 123 | 124 | - name: Cache Business Central Artifacts 125 | if: env.useCompilerFolder == 'True' && inputs.useArtifactCache && env.artifactCacheKey 126 | uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 127 | with: 128 | path: .artifactcache 129 | key: ${{ env.artifactCacheKey }} 130 | 131 | - name: Download Project Dependencies 132 | id: DownloadProjectDependencies 133 | uses: microsoft/AL-Go-Actions/DownloadProjectDependencies@v6.3 134 | env: 135 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 136 | with: 137 | shell: ${{ inputs.shell }} 138 | project: ${{ inputs.project }} 139 | buildMode: ${{ inputs.buildMode }} 140 | projectsDependenciesJson: ${{ inputs.projectDependenciesJson }} 141 | baselineWorkflowRunId: ${{ inputs.baselineWorkflowRunId }} 142 | 143 | - name: Build 144 | uses: microsoft/AL-Go-Actions/RunPipeline@v6.3 145 | env: 146 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 147 | BuildMode: ${{ inputs.buildMode }} 148 | with: 149 | shell: ${{ inputs.shell }} 150 | artifact: ${{ env.artifact }} 151 | project: ${{ inputs.project }} 152 | buildMode: ${{ inputs.buildMode }} 153 | installAppsJson: ${{ steps.DownloadProjectDependencies.outputs.DownloadedApps }} 154 | installTestAppsJson: ${{ steps.DownloadProjectDependencies.outputs.DownloadedTestApps }} 155 | 156 | - name: Sign 157 | if: inputs.signArtifacts && env.doNotSignApps == 'False' && (env.keyVaultCodesignCertificateName != '' || (fromJson(env.trustedSigning).Endpoint != '' && fromJson(env.trustedSigning).Account != '' && fromJson(env.trustedSigning).CertificateProfile != '')) 158 | id: sign 159 | uses: microsoft/AL-Go-Actions/Sign@v6.3 160 | with: 161 | shell: ${{ inputs.shell }} 162 | azureCredentialsJson: '${{ fromJson(steps.ReadSecrets.outputs.Secrets).AZURE_CREDENTIALS }}' 163 | pathToFiles: '${{ inputs.project }}/.buildartifacts/Apps/*.app' 164 | 165 | - name: Calculate Artifact names 166 | id: calculateArtifactsNames 167 | uses: microsoft/AL-Go-Actions/CalculateArtifactNames@v6.3 168 | if: success() || failure() 169 | with: 170 | shell: ${{ inputs.shell }} 171 | project: ${{ inputs.project }} 172 | buildMode: ${{ inputs.buildMode }} 173 | suffix: ${{ inputs.artifactsNameSuffix }} 174 | 175 | - name: Publish artifacts - apps 176 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 177 | if: inputs.artifactsRetentionDays >= 0 178 | with: 179 | name: ${{ steps.calculateArtifactsNames.outputs.AppsArtifactsName }} 180 | path: '${{ inputs.project }}/.buildartifacts/Apps/' 181 | if-no-files-found: ignore 182 | retention-days: ${{ inputs.artifactsRetentionDays }} 183 | 184 | - name: Publish artifacts - dependencies 185 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 186 | if: inputs.artifactsRetentionDays >= 0 && env.generateDependencyArtifact == 'True' 187 | with: 188 | name: ${{ steps.calculateArtifactsNames.outputs.DependenciesArtifactsName }} 189 | path: '${{ inputs.project }}/.buildartifacts/Dependencies/' 190 | if-no-files-found: ignore 191 | retention-days: ${{ inputs.artifactsRetentionDays }} 192 | 193 | - name: Publish artifacts - test apps 194 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 195 | if: inputs.artifactsRetentionDays >= 0 196 | with: 197 | name: ${{ steps.calculateArtifactsNames.outputs.TestAppsArtifactsName }} 198 | path: '${{ inputs.project }}/.buildartifacts/TestApps/' 199 | if-no-files-found: ignore 200 | retention-days: ${{ inputs.artifactsRetentionDays }} 201 | 202 | - name: Publish artifacts - build output 203 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 204 | if: (success() || failure()) && (hashFiles(format('{0}/BuildOutput.txt',inputs.project)) != '') 205 | with: 206 | name: ${{ steps.calculateArtifactsNames.outputs.BuildOutputArtifactsName }} 207 | path: '${{ inputs.project }}/BuildOutput.txt' 208 | if-no-files-found: ignore 209 | 210 | - name: Publish artifacts - container event log 211 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 212 | if: (failure()) && (hashFiles(format('{0}/ContainerEventLog.evtx',inputs.project)) != '') 213 | with: 214 | name: ${{ steps.calculateArtifactsNames.outputs.ContainerEventLogArtifactsName }} 215 | path: '${{ inputs.project }}/ContainerEventLog.evtx' 216 | if-no-files-found: ignore 217 | 218 | - name: Publish artifacts - test results 219 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 220 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/TestResults.xml',inputs.project)) != '') 221 | with: 222 | name: ${{ steps.calculateArtifactsNames.outputs.TestResultsArtifactsName }} 223 | path: '${{ inputs.project }}/.buildartifacts/TestResults.xml' 224 | if-no-files-found: ignore 225 | 226 | - name: Publish artifacts - bcpt test results 227 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 228 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/bcptTestResults.json',inputs.project)) != '') 229 | with: 230 | name: ${{ steps.calculateArtifactsNames.outputs.BcptTestResultsArtifactsName }} 231 | path: '${{ inputs.project }}/.buildartifacts/bcptTestResults.json' 232 | if-no-files-found: ignore 233 | 234 | - name: Publish artifacts - page scripting test results 235 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 236 | if: (success() || failure()) && (hashFiles(format('{0}/.buildartifacts/PageScriptingTestResults.xml',inputs.project)) != '') 237 | with: 238 | name: ${{ steps.calculateArtifactsNames.outputs.PageScriptingTestResultsArtifactsName }} 239 | path: '${{ inputs.project }}/.buildartifacts/PageScriptingTestResults.xml' 240 | if-no-files-found: ignore 241 | 242 | - name: Publish artifacts - page scripting test result details 243 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 244 | if: (success() || failure()) 245 | with: 246 | name: ${{ steps.calculateArtifactsNames.outputs.PageScriptingTestResultDetailsArtifactsName }} 247 | path: '${{ inputs.project }}/.buildartifacts/PageScriptingTestResultDetails/' 248 | if-no-files-found: ignore 249 | 250 | - name: Analyze Test Results 251 | id: analyzeTestResults 252 | if: (success() || failure()) && env.doNotRunTests == 'False' 253 | uses: microsoft/AL-Go-Actions/AnalyzeTests@v6.3 254 | with: 255 | shell: ${{ inputs.shell }} 256 | project: ${{ inputs.project }} 257 | 258 | - name: Cleanup 259 | if: always() 260 | uses: microsoft/AL-Go-Actions/PipelineCleanup@v6.3 261 | with: 262 | shell: ${{ inputs.shell }} 263 | project: ${{ inputs.project }} 264 | -------------------------------------------------------------------------------- /.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/*' ] 11 | 12 | defaults: 13 | run: 14 | shell: pwsh 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: [ ubuntu-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 | projectDependenciesJson: ${{ steps.determineProjectsToBuild.outputs.ProjectDependenciesJson }} 43 | buildOrderJson: ${{ steps.determineProjectsToBuild.outputs.BuildOrderJson }} 44 | powerPlatformSolutionFolder: ${{ steps.DeterminePowerPlatformSolutionFolder.outputs.powerPlatformSolutionFolder }} 45 | workflowDepth: ${{ steps.DetermineWorkflowDepth.outputs.WorkflowDepth }} 46 | steps: 47 | - name: Dump Workflow Information 48 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 49 | with: 50 | shell: pwsh 51 | 52 | - name: Checkout 53 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 54 | with: 55 | lfs: true 56 | 57 | - name: Initialize the workflow 58 | id: init 59 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v6.3 60 | with: 61 | shell: pwsh 62 | 63 | - name: Read settings 64 | id: ReadSettings 65 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 66 | with: 67 | shell: pwsh 68 | get: type,powerPlatformSolutionFolder,useGitSubmodules 69 | 70 | - name: Read submodules token 71 | id: ReadSubmodulesToken 72 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 73 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 74 | with: 75 | shell: pwsh 76 | gitHubSecrets: ${{ toJson(secrets) }} 77 | getSecrets: '-gitSubmodulesToken' 78 | 79 | - name: Checkout Submodules 80 | if: env.useGitSubmodules != 'false' && env.useGitSubmodules != '' 81 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 82 | with: 83 | lfs: true 84 | submodules: ${{ env.useGitSubmodules }} 85 | token: '${{ fromJson(steps.ReadSubmodulesToken.outputs.Secrets).gitSubmodulesToken }}' 86 | 87 | - name: Determine Workflow Depth 88 | id: DetermineWorkflowDepth 89 | run: | 90 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "WorkflowDepth=$($env:workflowDepth)" 91 | 92 | - name: Determine Projects To Build 93 | id: determineProjectsToBuild 94 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v6.3 95 | with: 96 | shell: pwsh 97 | maxBuildDepth: ${{ env.workflowDepth }} 98 | 99 | - name: Determine PowerPlatform Solution Folder 100 | id: DeterminePowerPlatformSolutionFolder 101 | if: env.type == 'PTE' 102 | run: | 103 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "powerPlatformSolutionFolder=$($env:powerPlatformSolutionFolder)" 104 | 105 | - name: Determine Delivery Target Secrets 106 | id: DetermineDeliveryTargetSecrets 107 | uses: microsoft/AL-Go-Actions/DetermineDeliveryTargets@v6.3 108 | with: 109 | shell: pwsh 110 | projectsJson: '${{ steps.determineProjectsToBuild.outputs.ProjectsJson }}' 111 | checkContextSecrets: 'false' 112 | 113 | - name: Read secrets 114 | id: ReadSecrets 115 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 116 | with: 117 | shell: pwsh 118 | gitHubSecrets: ${{ toJson(secrets) }} 119 | getSecrets: ${{ steps.DetermineDeliveryTargetSecrets.outputs.ContextSecrets }} 120 | 121 | - name: Determine Delivery Targets 122 | id: DetermineDeliveryTargets 123 | uses: microsoft/AL-Go-Actions/DetermineDeliveryTargets@v6.3 124 | env: 125 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 126 | with: 127 | shell: pwsh 128 | projectsJson: '${{ steps.determineProjectsToBuild.outputs.ProjectsJson }}' 129 | checkContextSecrets: 'true' 130 | 131 | - name: Determine Deployment Environments 132 | id: DetermineDeploymentEnvironments 133 | uses: microsoft/AL-Go-Actions/DetermineDeploymentEnvironments@v6.3 134 | env: 135 | GITHUB_TOKEN: ${{ github.token }} 136 | with: 137 | shell: pwsh 138 | getEnvironments: '*' 139 | type: 'CD' 140 | 141 | CheckForUpdates: 142 | needs: [ Initialization ] 143 | runs-on: [ ubuntu-latest ] 144 | steps: 145 | - name: Checkout 146 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 147 | 148 | - name: Read settings 149 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 150 | with: 151 | shell: pwsh 152 | get: templateUrl 153 | 154 | - name: Check for updates to AL-Go system files 155 | uses: microsoft/AL-Go-Actions/CheckForUpdates@v6.3 156 | with: 157 | shell: pwsh 158 | templateUrl: ${{ env.templateUrl }} 159 | downloadLatest: true 160 | 161 | Build: 162 | needs: [ Initialization ] 163 | if: (!failure()) && (!cancelled()) && fromJson(needs.Initialization.outputs.buildOrderJson)[0].projectsCount > 0 164 | strategy: 165 | matrix: 166 | include: ${{ fromJson(needs.Initialization.outputs.buildOrderJson)[0].buildDimensions }} 167 | fail-fast: false 168 | name: Build ${{ matrix.projectName }} (${{ matrix.buildMode }}) 169 | uses: ./.github/workflows/_BuildALGoProject.yaml 170 | secrets: inherit 171 | with: 172 | shell: ${{ matrix.githubRunnerShell }} 173 | runsOn: ${{ matrix.githubRunner }} 174 | project: ${{ matrix.project }} 175 | projectName: ${{ matrix.projectName }} 176 | buildMode: ${{ matrix.buildMode }} 177 | projectDependenciesJson: ${{ needs.Initialization.outputs.projectDependenciesJson }} 178 | secrets: 'licenseFileUrl,codeSignCertificateUrl,*codeSignCertificatePassword,keyVaultCertificateUrl,*keyVaultCertificatePassword,keyVaultClientId,gitHubPackagesContext,applicationInsightsConnectionString' 179 | signArtifacts: true 180 | useArtifactCache: true 181 | 182 | DeployALDoc: 183 | needs: [ Initialization, Build ] 184 | if: (!cancelled()) && needs.Build.result == 'Success' && needs.Initialization.outputs.generateALDocArtifact == 1 && github.ref_name == 'main' 185 | runs-on: [ ubuntu-latest ] 186 | name: Deploy Reference Documentation 187 | permissions: 188 | contents: read 189 | actions: read 190 | pages: write 191 | id-token: write 192 | environment: 193 | name: github-pages 194 | url: ${{ steps.deployment.outputs.page_url }} 195 | steps: 196 | - name: Checkout 197 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 198 | 199 | - name: Download artifacts 200 | uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 201 | with: 202 | path: '.artifacts' 203 | 204 | - name: Read settings 205 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 206 | with: 207 | shell: pwsh 208 | 209 | - name: Setup Pages 210 | if: needs.Initialization.outputs.deployALDocArtifact == 1 211 | uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 212 | 213 | - name: Build Reference Documentation 214 | uses: microsoft/AL-Go-Actions/BuildReferenceDocumentation@v6.3 215 | with: 216 | shell: pwsh 217 | artifacts: '.artifacts' 218 | 219 | - name: Upload pages artifact 220 | uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 221 | with: 222 | path: ".aldoc/_site/" 223 | 224 | - name: Deploy to GitHub Pages 225 | if: needs.Initialization.outputs.deployALDocArtifact == 1 226 | id: deployment 227 | uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 228 | 229 | Deploy: 230 | needs: [ Initialization, Build ] 231 | if: (!cancelled()) && (needs.Build.result == 'success' || needs.Build.result == 'skipped') && needs.Initialization.outputs.environmentCount > 0 232 | strategy: ${{ fromJson(needs.Initialization.outputs.environmentsMatrixJson) }} 233 | runs-on: ${{ fromJson(matrix.os) }} 234 | name: Deploy to ${{ matrix.environment }} 235 | defaults: 236 | run: 237 | shell: ${{ matrix.shell }} 238 | environment: 239 | name: ${{ matrix.environment }} 240 | url: ${{ steps.Deploy.outputs.environmentUrl }} 241 | steps: 242 | - name: Checkout 243 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 244 | 245 | - name: Download artifacts 246 | uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 247 | with: 248 | path: '.artifacts' 249 | 250 | - name: Read settings 251 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 252 | with: 253 | shell: ${{ matrix.shell }} 254 | get: type,powerPlatformSolutionFolder 255 | 256 | - name: EnvName 257 | id: envName 258 | run: | 259 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 260 | $envName = '${{ matrix.environment }}'.split(' ')[0] 261 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "envName=$envName" 262 | 263 | - name: Read secrets 264 | id: ReadSecrets 265 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 266 | with: 267 | shell: ${{ matrix.shell }} 268 | gitHubSecrets: ${{ toJson(secrets) }} 269 | getSecrets: '${{ steps.envName.outputs.envName }}-AuthContext,${{ steps.envName.outputs.envName }}_AuthContext,AuthContext' 270 | 271 | - name: Deploy to Business Central 272 | id: Deploy 273 | uses: microsoft/AL-Go-Actions/Deploy@v6.3 274 | env: 275 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 276 | with: 277 | shell: ${{ matrix.shell }} 278 | environmentName: ${{ matrix.environment }} 279 | artifactsFolder: '.artifacts' 280 | type: 'CD' 281 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 282 | 283 | - name: Deploy to Power Platform 284 | if: env.type == 'PTE' && env.powerPlatformSolutionFolder != '' 285 | uses: microsoft/AL-Go-Actions/DeployPowerPlatform@v6.3 286 | env: 287 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 288 | with: 289 | shell: pwsh 290 | environmentName: ${{ matrix.environment }} 291 | artifactsFolder: '.artifacts' 292 | deploymentEnvironmentsJson: ${{ needs.Initialization.outputs.deploymentEnvironmentsJson }} 293 | 294 | Deliver: 295 | needs: [ Initialization, Build ] 296 | if: (!cancelled()) && (needs.Build.result == 'success' || needs.Build.result == 'skipped') && needs.Initialization.outputs.deliveryTargetsJson != '[]' 297 | strategy: 298 | matrix: 299 | deliveryTarget: ${{ fromJson(needs.Initialization.outputs.deliveryTargetsJson) }} 300 | fail-fast: false 301 | runs-on: [ ubuntu-latest ] 302 | name: Deliver to ${{ matrix.deliveryTarget }} 303 | steps: 304 | - name: Checkout 305 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 306 | 307 | - name: Download artifacts 308 | uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 309 | with: 310 | path: '.artifacts' 311 | 312 | - name: Read settings 313 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 314 | with: 315 | shell: pwsh 316 | 317 | - name: Read secrets 318 | id: ReadSecrets 319 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 320 | with: 321 | shell: pwsh 322 | gitHubSecrets: ${{ toJson(secrets) }} 323 | getSecrets: '${{ matrix.deliveryTarget }}Context' 324 | 325 | - name: Deliver 326 | uses: microsoft/AL-Go-Actions/Deliver@v6.3 327 | env: 328 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 329 | with: 330 | shell: pwsh 331 | type: 'CD' 332 | projects: ${{ needs.Initialization.outputs.projects }} 333 | deliveryTarget: ${{ matrix.deliveryTarget }} 334 | artifacts: '.artifacts' 335 | 336 | PostProcess: 337 | needs: [ Initialization, Build, Deploy, Deliver, DeployALDoc ] 338 | if: (!cancelled()) 339 | runs-on: [ ubuntu-latest ] 340 | steps: 341 | - name: Checkout 342 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 343 | 344 | - name: Finalize the workflow 345 | id: PostProcess 346 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v6.3 347 | env: 348 | GITHUB_TOKEN: ${{ github.token }} 349 | with: 350 | shell: pwsh 351 | telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} 352 | currentJobContext: ${{ toJson(job) }} 353 | -------------------------------------------------------------------------------- /.github/workflows/CreateRelease.yaml: -------------------------------------------------------------------------------- 1 | name: ' Create release' 2 | run-name: "Create release - Version ${{ inputs.tag }}" 3 | 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | appVersion: 8 | description: App version to promote to release (default is latest) 9 | required: false 10 | default: 'latest' 11 | name: 12 | description: Name of this release 13 | required: true 14 | default: '' 15 | tag: 16 | description: Tag of this release (needs to be semantic version string https://semver.org, ex. 1.0.0) 17 | required: true 18 | default: '' 19 | releaseType: 20 | description: Release, prerelease or draft? 21 | type: choice 22 | options: 23 | - Release 24 | - Prerelease 25 | - Draft 26 | default: Release 27 | createReleaseBranch: 28 | description: Create Release Branch? 29 | type: boolean 30 | default: false 31 | releaseBranchPrefix: 32 | description: The prefix for the release branch. Used only if 'Create Release Branch?' is checked. 33 | type: string 34 | default: release/ 35 | updateVersionNumber: 36 | 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. 37 | required: false 38 | default: '' 39 | skipUpdatingDependencies: 40 | description: Skip updating dependency version numbers in all apps. 41 | type: boolean 42 | default: false 43 | directCommit: 44 | description: Direct Commit? 45 | type: boolean 46 | default: false 47 | useGhTokenWorkflow: 48 | description: Use GhTokenWorkflow for PR/Commit? 49 | type: boolean 50 | default: false 51 | 52 | permissions: 53 | actions: read 54 | contents: write 55 | id-token: write 56 | pull-requests: write 57 | 58 | concurrency: release 59 | 60 | defaults: 61 | run: 62 | shell: pwsh 63 | 64 | env: 65 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 66 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 67 | 68 | jobs: 69 | CreateRelease: 70 | needs: [ ] 71 | runs-on: [ ubuntu-latest ] 72 | outputs: 73 | artifacts: ${{ steps.analyzeartifacts.outputs.artifacts }} 74 | releaseId: ${{ steps.createrelease.outputs.releaseId }} 75 | commitish: ${{ steps.analyzeartifacts.outputs.commitish }} 76 | releaseVersion: ${{ steps.createreleasenotes.outputs.releaseVersion }} 77 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 78 | steps: 79 | - name: Dump Workflow Information 80 | uses: microsoft/AL-Go-Actions/DumpWorkflowInfo@v6.3 81 | with: 82 | shell: pwsh 83 | 84 | - name: Checkout 85 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 86 | 87 | - name: Initialize the workflow 88 | id: init 89 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@v6.3 90 | with: 91 | shell: pwsh 92 | 93 | - name: Read settings 94 | id: ReadSettings 95 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 96 | with: 97 | shell: pwsh 98 | get: templateUrl,repoName,type,powerPlatformSolutionFolder 99 | 100 | - name: Read secrets 101 | id: ReadSecrets 102 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 103 | with: 104 | shell: pwsh 105 | gitHubSecrets: ${{ toJson(secrets) }} 106 | getSecrets: 'TokenForPush' 107 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 108 | 109 | - name: Determine Projects 110 | id: determineProjects 111 | uses: microsoft/AL-Go-Actions/DetermineProjectsToBuild@v6.3 112 | with: 113 | shell: pwsh 114 | 115 | - name: Check for updates to AL-Go system files 116 | uses: microsoft/AL-Go-Actions/CheckForUpdates@v6.3 117 | with: 118 | shell: pwsh 119 | templateUrl: ${{ env.templateUrl }} 120 | downloadLatest: true 121 | 122 | - name: Analyze Artifacts 123 | id: analyzeartifacts 124 | env: 125 | _appVersion: ${{ github.event.inputs.appVersion }} 126 | run: | 127 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 128 | $projects = '${{ steps.determineProjects.outputs.ProjectsJson }}' | ConvertFrom-Json 129 | Write-Host "projects:" 130 | $projects | ForEach-Object { Write-Host "- $_" } 131 | if ($env:type -eq "PTE" -and $env:powerPlatformSolutionFolder -ne "") { 132 | Write-Host "PowerPlatformSolution:" 133 | Write-Host "- $($env:powerPlatformSolutionFolder)" 134 | $projects += @($env:powerPlatformSolutionFolder) 135 | } 136 | $include = @() 137 | $sha = '' 138 | $allArtifacts = @() 139 | $page = 1 140 | $headers = @{ 141 | "Authorization" = "token ${{ github.token }}" 142 | "X-GitHub-Api-Version" = "2022-11-28" 143 | "Accept" = "application/vnd.github+json; charset=utf-8" 144 | } 145 | do { 146 | $repoArtifacts = Invoke-RestMethod -UseBasicParsing -Headers $headers -Uri "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/actions/artifacts?per_page=100&page=$page" 147 | $allArtifacts += $repoArtifacts.Artifacts | Where-Object { !$_.expired } 148 | $page++ 149 | } 150 | while ($repoArtifacts.Artifacts.Count -gt 0) 151 | Write-Host "Repo Artifacts count: $($repoArtifacts.total_count)" 152 | Write-Host "Downloaded Artifacts count: $($allArtifacts.Count)" 153 | $projects | ForEach-Object { 154 | $thisProject = $_ 155 | if ($thisProject -and ($thisProject -ne '.')) { 156 | $project = $thisProject.Replace('\','_').Replace('/','_') 157 | } 158 | else { 159 | $project = $env:repoName 160 | } 161 | $refname = "$ENV:GITHUB_REF_NAME".Replace('/','_') 162 | Write-Host "Analyzing artifacts for project $project" 163 | $appVersion = "$env:_appVersion" 164 | if ($appVersion -eq "latest") { 165 | Write-Host "Grab latest" 166 | $artifact = $allArtifacts | Where-Object { $_.name -like "$project-$refname-Apps-*" -or $_.name -like "$project-$refname-PowerPlatformSolution-*" } | Select-Object -First 1 167 | } 168 | else { 169 | Write-Host "Search for $project-$refname-Apps-$appVersion or $project-$refname-PowerPlatformSolution-$appVersion" 170 | $artifact = $allArtifacts | Where-Object { $_.name -eq "$project-$refname-Apps-$appVersion"-or $_.name -eq "$project-$refname-PowerPlatformSolution-$appVersion" } | Select-Object -First 1 171 | } 172 | if ($artifact) { 173 | $startIndex = $artifact.name.LastIndexOf('-') + 1 174 | $artifactsVersion = $artifact.name.SubString($startIndex) 175 | } 176 | else { 177 | Write-Host "::Error::No artifacts found for this project" 178 | exit 1 179 | } 180 | if ($sha) { 181 | if ($artifact.workflow_run.head_sha -ne $sha) { 182 | 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." 183 | 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." 184 | } 185 | } 186 | else { 187 | $sha = $artifact.workflow_run.head_sha 188 | } 189 | 190 | Write-host "Looking for $project-$refname-Apps-$artifactsVersion or $project-$refname-TestApps-$artifactsVersion or $project-$refname-Dependencies-$artifactsVersion or $project-$refname-PowerPlatformSolution-$artifactsVersion" 191 | $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 { 192 | $atype = $_.name.SubString(0,$_.name.Length-$artifactsVersion.Length-1) 193 | $atype = $atype.SubString($atype.LastIndexOf('-')+1) 194 | $include += $( [ordered]@{ "name" = $_.name; "url" = $_.archive_download_url; "atype" = $atype; "project" = $thisproject } ) 195 | } 196 | if ($include.Count -eq 0) { 197 | Write-Host "::Error::No artifacts found for version $artifactsVersion" 198 | exit 1 199 | } 200 | } 201 | $artifacts = @{ "include" = $include } 202 | $artifactsJson = $artifacts | ConvertTo-Json -compress 203 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "artifacts=$artifactsJson" 204 | Write-Host "artifacts=$artifactsJson" 205 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "commitish=$sha" 206 | Write-Host "commitish=$sha" 207 | 208 | - name: Prepare release notes 209 | id: createreleasenotes 210 | uses: microsoft/AL-Go-Actions/CreateReleaseNotes@v6.3 211 | with: 212 | shell: pwsh 213 | tag_name: ${{ github.event.inputs.tag }} 214 | target_commitish: ${{ steps.analyzeartifacts.outputs.commitish }} 215 | 216 | - name: Create release 217 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 218 | id: createrelease 219 | env: 220 | bodyMD: ${{ steps.createreleasenotes.outputs.releaseNotes }} 221 | with: 222 | github-token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 223 | script: | 224 | var bodyMD = process.env.bodyMD 225 | const createReleaseResponse = await github.rest.repos.createRelease({ 226 | owner: context.repo.owner, 227 | repo: context.repo.repo, 228 | tag_name: '${{ github.event.inputs.tag }}', 229 | name: '${{ github.event.inputs.name }}', 230 | body: bodyMD.replaceAll('\\n','\n').replaceAll('%0A','\n').replaceAll('%0D','\n').replaceAll('%25','%'), 231 | draft: ${{ github.event.inputs.releaseType=='Draft' }}, 232 | prerelease: ${{ github.event.inputs.releaseType=='Prerelease' }}, 233 | make_latest: 'legacy', 234 | target_commitish: '${{ steps.analyzeartifacts.outputs.commitish }}' 235 | }); 236 | const { 237 | data: { id: releaseId, html_url: htmlUrl, upload_url: uploadUrl } 238 | } = createReleaseResponse; 239 | core.setOutput('releaseId', releaseId); 240 | 241 | UploadArtifacts: 242 | needs: [ CreateRelease ] 243 | runs-on: [ ubuntu-latest ] 244 | strategy: 245 | matrix: ${{ fromJson(needs.CreateRelease.outputs.artifacts) }} 246 | fail-fast: true 247 | steps: 248 | - name: Checkout 249 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 250 | 251 | - name: Read settings 252 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 253 | with: 254 | shell: pwsh 255 | 256 | - name: Read secrets 257 | id: ReadSecrets 258 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 259 | with: 260 | shell: pwsh 261 | gitHubSecrets: ${{ toJson(secrets) }} 262 | getSecrets: 'nuGetContext,storageContext,TokenForPush' 263 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 264 | 265 | - name: Download artifact 266 | run: | 267 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 268 | Write-Host "Downloading artifact ${{ matrix.name}}" 269 | $headers = @{ 270 | "Authorization" = "token ${{ github.token }}" 271 | "X-GitHub-Api-Version" = "2022-11-28" 272 | "Accept" = "application/vnd.github+json" 273 | } 274 | Invoke-WebRequest -UseBasicParsing -Headers $headers -Uri '${{ matrix.url }}' -OutFile '${{ matrix.name }}.zip' 275 | 276 | - name: Upload release artifacts 277 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 278 | env: 279 | releaseId: ${{ needs.createrelease.outputs.releaseId }} 280 | with: 281 | github-token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 282 | script: | 283 | const releaseId = process.env.releaseId 284 | const assetPath = '${{ matrix.name }}.zip' 285 | const assetName = encodeURIComponent('${{ matrix.name }}.zip'.replaceAll(' ','.')).replaceAll('%','') 286 | const fs = require('fs'); 287 | const uploadAssetResponse = await github.rest.repos.uploadReleaseAsset({ 288 | owner: context.repo.owner, 289 | repo: context.repo.repo, 290 | release_id: releaseId, 291 | name: assetName, 292 | data: fs.readFileSync(assetPath) 293 | }); 294 | 295 | - name: Deliver to NuGet 296 | uses: microsoft/AL-Go-Actions/Deliver@v6.3 297 | if: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).nuGetContext != '' }} 298 | env: 299 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 300 | with: 301 | shell: pwsh 302 | type: 'Release' 303 | projects: ${{ matrix.project }} 304 | deliveryTarget: 'NuGet' 305 | artifacts: ${{ github.event.inputs.appVersion }} 306 | atypes: 'Apps,TestApps' 307 | 308 | - name: Deliver to Storage 309 | uses: microsoft/AL-Go-Actions/Deliver@v6.3 310 | if: ${{ fromJson(steps.ReadSecrets.outputs.Secrets).storageContext != '' }} 311 | env: 312 | Secrets: '${{ steps.ReadSecrets.outputs.Secrets }}' 313 | with: 314 | shell: pwsh 315 | type: 'Release' 316 | projects: ${{ matrix.project }} 317 | deliveryTarget: 'Storage' 318 | artifacts: ${{ github.event.inputs.appVersion }} 319 | atypes: 'Apps,TestApps,Dependencies' 320 | 321 | CreateReleaseBranch: 322 | needs: [ CreateRelease, UploadArtifacts ] 323 | if: ${{ github.event.inputs.createReleaseBranch=='true' }} 324 | runs-on: [ ubuntu-latest ] 325 | steps: 326 | - name: Checkout 327 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 328 | with: 329 | ref: '${{ needs.createRelease.outputs.commitish }}' 330 | 331 | - name: Create Release Branch 332 | env: 333 | releaseBranchPrefix: ${{ github.event.inputs.releaseBranchPrefix }} 334 | run: | 335 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 336 | $releaseBranch = "$($env:releaseBranchPrefix)" + "${{ needs.CreateRelease.outputs.releaseVersion }}" 337 | Write-Host "Creating release branch $releaseBranch" 338 | git checkout -b $releaseBranch 339 | git config user.name ${{ github.actor}} 340 | git config user.email ${{ github.actor}}@users.noreply.github.com 341 | git commit --allow-empty -m "Release branch $releaseBranch" 342 | git push origin $releaseBranch 343 | 344 | UpdateVersionNumber: 345 | needs: [ CreateRelease, UploadArtifacts ] 346 | if: ${{ github.event.inputs.updateVersionNumber!='' }} 347 | runs-on: [ ubuntu-latest ] 348 | steps: 349 | - name: Checkout 350 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 351 | 352 | - name: Read settings 353 | uses: microsoft/AL-Go-Actions/ReadSettings@v6.3 354 | with: 355 | shell: pwsh 356 | 357 | - name: Read secrets 358 | id: ReadSecrets 359 | uses: microsoft/AL-Go-Actions/ReadSecrets@v6.3 360 | with: 361 | shell: pwsh 362 | gitHubSecrets: ${{ toJson(secrets) }} 363 | getSecrets: 'TokenForPush' 364 | useGhTokenWorkflowForPush: '${{ github.event.inputs.useGhTokenWorkflow }}' 365 | 366 | - name: Update Version Number 367 | uses: microsoft/AL-Go-Actions/IncrementVersionNumber@v6.3 368 | with: 369 | shell: pwsh 370 | token: ${{ steps.ReadSecrets.outputs.TokenForPush }} 371 | versionNumber: ${{ github.event.inputs.updateVersionNumber }} 372 | skipUpdatingDependencies: ${{ github.event.inputs.skipUpdatingDependencies }} 373 | directCommit: ${{ github.event.inputs.directCommit }} 374 | 375 | PostProcess: 376 | needs: [ CreateRelease, UploadArtifacts, CreateReleaseBranch, UpdateVersionNumber ] 377 | if: always() 378 | runs-on: [ ubuntu-latest ] 379 | steps: 380 | - name: Checkout 381 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 382 | 383 | - name: Finalize the workflow 384 | id: PostProcess 385 | uses: microsoft/AL-Go-Actions/WorkflowPostProcess@v6.3 386 | env: 387 | GITHUB_TOKEN: ${{ github.token }} 388 | with: 389 | shell: pwsh 390 | telemetryScopeJson: ${{ needs.CreateRelease.outputs.telemetryScopeJson }} 391 | currentJobContext: ${{ toJson(job) }} 392 | -------------------------------------------------------------------------------- /.github/RELEASENOTES.copy.md: -------------------------------------------------------------------------------- 1 | ## v6.3 2 | 3 | ### Deprecations 4 | 5 | - `cleanModePreprocessorSymbols` will be removed after April 1st 2025. Use [Conditional Settings](https://aka.ms/algosettings#conditional-settings) instead, specifying buildModes and the `preprocessorSymbols` setting. Read [this](https://aka.ms/algodeprecations#cleanModePreprocessorSymbols) for more information. 6 | 7 | ### Issues 8 | 9 | - It is now possible to skip the modification of dependency version numbers when running the Increment Version number workflow or the Create Release workflow 10 | 11 | ### New Repository Settings 12 | 13 | - [`shortLivedArtifactsRetentionDays`](https://aka.ms/algosettings#shortLivedArtifactsRetentionDays) determines the number of days to keep short lived build artifacts (f.ex build artifacts from pull request builds, next minor or next major builds). 1 is default. 0 means use GitHub default. 14 | - [`preProcessorSymbols`](https://aka.ms/algosettings#preProcessorSymbols) is a list of preprocessor symbols to use when building the apps. This setting can be specified in [workflow specific settings files](https://aka.ms/algosettings#where-are-the-settings-located) or in [conditional settings](https://aka.ms/algosettings#conditional-settings). 15 | 16 | ### New Versioning Strategy 17 | 18 | Setting versioning strategy to 3 will allow 3 segments of the version number to be defined in app.json and repoVersion. Only the 4th segment (Revision) will be defined by the GitHub [run_number](https://go.microsoft.com/fwlink/?linkid=2217416&clcid=0x409) for the CI/CD workflow. Increment version number and Create Release now also supports the ability to set a third segment to the RepoVersion and appversion in app.json. 19 | 20 | ### Change in published artifacts 21 | 22 | When using `useProjectDependencies` in a multi-project repository, AL-Go for GitHub used to generate short lived build artifacts called `thisBuild---...`. This is no longer the case. Instead, normal build artifacts will be published and used by depending projects. The retention period for the short lived artifacts generated are controlled by a settings called [`shortLivedArtifactsRetentionDays`](https://aka.ms/algosettings#shortLivedArtifactsRetentionDays). 23 | 24 | ### Preprocessor symbols 25 | 26 | It is now possible to define preprocessor symbols, which will be used when building your apps using the [`preProcessorSymbols`](https://aka.ms/algosettings#preProcessorSymbols) setting. This setting can be specified in workflow specific settings file or it can be used in conditional settings. 27 | 28 | ## v6.2 29 | 30 | ### Issues 31 | 32 | - Issue 1296 Make property "appFolders" optional 33 | - Issue 1344 Experimental feature "git submodules" seems to be a breaking change 34 | - Issue 1305 Extra telemetry Property RepositoryOwner and RepositoryName¨ 35 | - Add RunnerEnvironment to Telemetry 36 | - Output a notice, not a warning, when there are no available updates for AL-Go for GitHub 37 | 38 | ### New Repository Settings 39 | 40 | - `useGitSubmodules` can be either `true` or `recursive` if you want to enable Git Submodules in your repository. If your Git submodules resides in a private repository, you need to create a secret called `gitSubmodulesToken` containing a PAT with access to the submodule repositories. Like with all other secrets, you can also create a setting called `gitSubmodulesTokenSecretName` and specify the name of another secret, with these permissions (f.ex. ghTokenWorkflow). 41 | - `commitOptions` - is a structure defining how you want AL-Go to handle automated commits or pull requests coming from AL-Go (e.g. for Update AL-Go System Files). The structure contains the following properties 42 | - `messageSuffix` : A string you want to append to the end of commits/pull requests created by AL-Go. This can be useful if you are using the Azure Boards integration (or similar integration) to link commits to workitems. 43 | - `pullRequestAutoMerge` : A boolean defining whether you want AL-Go pull requests to be set to auto-complete. This will auto-complete the pull requests once all checks are green and all required reviewers have approved. 44 | - `pullRequestLabels` : A list of labels to add to the pull request. The labels need to be created in the repository before they can be applied. 45 | 46 | ### Support for Git submodules 47 | 48 | In v6.1 we added experimental support for Git submodules - this did however only work if the submodules was in a public repository. In this version, you can use the `useGitSubmodules` setting to control whether you want to use Git Submodules and the `gitSubmodulesToken` secret to allow permission to read these repositories. 49 | 50 | ## v6.1 51 | 52 | ### Issues 53 | 54 | - Issue 1241 Increment Version Number might produce wrong app.json 55 | - When auto discovering appFolders, testFolders and bcptTestFolders - if a BCPT Test app has a dependency to a test framework app, it is added to testFolders as well as bcptTestFolders and will cause a failure. 56 | 57 | ### New Project Settings 58 | 59 | - `pageScriptingTests` should be an array of page scripting test file specifications, relative to the AL-Go project. Examples of file specifications: `recordings/my*.yml` (for all yaml files in the recordings subfolder matching my\*.yml), `recordings` (for all \*.yml files in the recordings subfolder) or `recordings/test.yml` (for a single yml file) 60 | - `doNotRunPageScriptingTests` can force the pipeline to NOT run the page scripting tests specified in pageScriptingTests. Note this setting can be set in a [workflow specific settings file](#where-are-the-settings-located) to only apply to that workflow 61 | - `restoreDatabases` should be an array of events, indicating when you want to start with clean databases in the container. Possible events are: `BeforeBcpTests`, `BeforePageScriptingTests`, `BeforeEachTestApp`, `BeforeEachBcptTestApp`, `BeforeEachPageScriptingTest` 62 | 63 | ### New Repository Settings 64 | 65 | - `trustedSigning` is a structure defining `Account`, `EndPoint` and `CertificateProfile` if you want to use trusted signing. Note that your Azure_Credentials secret (Microsoft Entra ID App or Managed identity) still needs to provide access to your azure subscription and be assigned the `Trusted Signing Certificate Profile Signer` role in the Trusted Signing Account. 66 | - `deployTo` now has an additional property called DependencyInstallMode, which determines how dependencies are deployed if GenerateDependencyArtifact is true. Default value is `install` to install dependencies if not already installed. Other values are `ignore` for ignoring dependencies, `upgrade` for upgrading dependencies if possible and `forceUpgrade` for force upgrading dependencies. 67 | 68 | ### Support for Azure Trusted Signing 69 | 70 | Read https://learn.microsoft.com/en-us/azure/trusted-signing/ for more information about Trusted Signing and how to set it up. After setting up your trusted signing account and certificate profile, you need to create a setting called [trustedSigning](https://aka.ms/algosettings#trustedSigning) for AL-Go to sign your apps using Azure Trusted Signing. 71 | 72 | ### Support for Page Scripting Tests 73 | 74 | Page Scripting tests are now supported as part of CI/CD. By specifying pageScriptingTests in your project settings file, AL-Go for GitHub will automatically run these page scripting tests as part of your CI/CD workflow, generating the following build artifacts: 75 | 76 | - `PageScriptingTestResults` is a JUnit test results file with all results combined. 77 | - `PageScriptingTestResultDetails` are the detailed test results (including videos) when any of the page scripting tests have failures. If the page scripting tests succeed - the details are not published. 78 | 79 | ### Experimental support for Git submodule 80 | 81 | [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) is now supported as part of CI/CD on your project. 82 | 83 | ## v6.0 84 | 85 | ### Issues 86 | 87 | - Issue 1184 Publish to Environment fails on 'Permission Denied' 88 | - AL Language extension in 25.0 doesn't contain the linux executable, use dotnet to invoke the dll instead. 89 | 90 | ### New Settings 91 | 92 | - `deliverTo` now has an additional property called `ContinuousDelivery`, indicating whether or not to run continuous delivery to this deliveryTarget. Default is true. 93 | - `trustMicrosoftNuGetFeeds` Unless this setting is set to false, AL-Go for GitHub will trust the NuGet feeds provided by Microsoft. The feeds provided by Microsoft contains all Microsoft apps, all Microsoft symbols and symbols for all AppSource apps. 94 | - `trustedNuGetFeeds` - can be an array of NuGet feed specifications, which AL-Go for GitHub will use for dependency resolution. Every feed specification must include a URL property and can optionally include a few other properties: 95 | - url - The URL of the feed (examples: https://pkgs.dev.azure.com/myorg/apps/\_packaging/myrepo/nuget/v3/index.json or https://nuget.pkg.github.com/mygithuborg/index.json"). 96 | - patterns - AL-Go for GitHub will only trust packages, where the ID matches this pattern. Default is all packages (\*). 97 | - fingerprints - If specified, AL-Go for GitHub will only trust packages signed with a certificate with a fingerprint matching one of the fingerprints in this array. 98 | - authTokenSecret - If the NuGet feed specified by URL is private, the authTokenSecret must be the name of a secret containing the authentication token with permissions to search and read packages from the NuGet feed. 99 | 100 | ### Support for delivering to GitHub Packages and NuGet 101 | 102 | With this release the implementation for delivering to NuGet packages (by adding the NuGetContext secret), is similar to the functionality behind delivering to GitHub packages and the implementation is no longer in preview. 103 | 104 | ### Allow GitHubRunner and GitHubRunnerShell as project settings 105 | 106 | Previously, AL-Go required the GitHubRunner and GitHubRunnerShell settings to be set on repository level. This has now been changed such that they can be set on project level. 107 | 108 | ## v5.3 109 | 110 | ### Issues 111 | 112 | - Issue 1105 Increment Version Number - repoVersion in .github/AL-Go-Settings.json is not updated 113 | - Issue 1073 Publish to AppSource - Automated validation: failure 114 | - Issue 980 Allow Scope to be PTE in continuousDeployment for PTE extensions in Sandbox (enhancement request) 115 | - Issue 1079 AppSource App deployment failes with PerTenantExtensionCop Error PTE0001 and PTE0002 116 | - Issue 866 Accessing GitHub Environment Variables in DeployToCustom Scenarios for PowerShell Scripts 117 | - Issue 1083 SyncMode for custom deployments? 118 | - Issue 1109 Why filter deployment settings? 119 | - Fix issue with github ref when running reusable workflows 120 | - Issue 1098 Support for specifying the name of the AZURE_CREDENTIALS secret by adding a AZURE_CREDENTIALSSecretName setting 121 | - Fix placeholder syntax for git ref in PullRequestHandler.yaml 122 | - Issue 1164 Getting secrets from Azure key vault fails in Preview 123 | 124 | ### Dependencies to PowerShell modules 125 | 126 | AL-Go for GitHub relies on specific PowerShell modules, and the minimum versions required for these modules are tracked in [Packages.json](https://raw.githubusercontent.com/microsoft/AL-Go/main/Actions/Packages.json) file. Should the installed modules on the GitHub runner not meet these minimum requirements, the necessary modules will be installed as needed. 127 | 128 | ### Support managed identities and federated credentials 129 | 130 | All authentication context secrets now supports managed identities and federated credentials. See more [here](Scenarios/secrets.md). Furthermore, you can now use https://aka.ms/algosecrets#authcontext to learn more about the formatting of that secret. 131 | 132 | ### Business Central Performance Toolkit Test Result Viewer 133 | 134 | In the summary after a Test Run, you now also have the result of performance tests. 135 | 136 | ### Support Ubuntu runners for all AL-Go workflows 137 | 138 | Previously, the workflows "Update AL-Go System Files" and "TroubleShooting" were hardcoded to always run on `windows-latest` to prevent deadlocks and security issues. 139 | From now on, `ubuntu-lates` will also be allowed for these mission critical workflows, when changing the `runs-on` setting. Additionally, only the value `pwsh` for `shell` setting is allowed when using `ubuntu-latest` runners. 140 | 141 | ### Updated AL-Go telemetry 142 | 143 | AL-Go for GitHub now includes a new telemetry module. For detailed information on how to enable or disable telemetry and to see what data AL-Go logs, check out [this article](https://github.com/microsoft/AL-Go/blob/main/Scenarios/EnablingTelemetry.md). 144 | 145 | ### New Settings 146 | 147 | - `deployTo`: is not really new, but has a new property: 148 | 149 | - **Scope** = specifies the scope of the deployment: Dev, PTE. If not specified, AL-Go for GitHub will always use the Dev Scope for AppSource Apps, but also for PTEs when deploying to sandbox environments when impersonation (refreshtoken) is used for authentication. 150 | - **BuildMode** = specifies which buildMode to use for the deployment. Default is to use the Default buildMode. 151 | - **\** = custom properties are now supported and will be transferred to a custom deployment script in the hashtable. 152 | 153 | - `bcptThresholds` is a JSON object with properties for the default thresholds for the Business Central Performance Toolkit 154 | 155 | - **DurationWarning** - a warning is issued if the duration of a bcpt test degrades more than this percentage (default 10) 156 | - **DurationError** - an error is issued if the duration of a bcpt test degrades more than this percentage (default 25) 157 | - **NumberOfSqlStmtsWarning** - a warning is issued if the number of SQL statements from a bcpt test increases more than this percentage (default 5) 158 | - **NumberOfSqlStmtsError** - an error is issued if the number of SQL statements from a bcpt test increases more than this percentage (default 10) 159 | 160 | > [!NOTE] 161 | > Duration thresholds are subject to varying results depending on the performance of the agent running the tests. Number of SQL statements executed by a test is often the most reliable indicator of performance degredation. 162 | 163 | ## v5.2 164 | 165 | ### Issues 166 | 167 | - Issue 1084 Automatic updates for AL-Go are failing when main branch requires Pull Request 168 | 169 | ### New Settings 170 | 171 | - `PowerPlatformSolutionFolder`: Contains the name of the folder containing a PowerPlatform Solution (only one) 172 | - `DeployTo` now has two additional properties `companyId` is the Company Id from Business Central (for PowerPlatform connection) and `ppEnvironmentUrl` is the Url of the PowerPlatform environment to deploy to. 173 | 174 | ### New Actions 175 | 176 | - `BuildPowerPlatform`: to build a PowerPlatform Solution 177 | - `DeployPowerPlatform`: to deploy a PowerPlatform Solution 178 | - `PullPowerPlatformChanges`: to pull changes made in PowerPlatform studio into the repository 179 | - `ReadPowerPlatformSettings`: to read settings and secrets for PowerPlatform deployment 180 | - `GetArtifactsForDeployment`: originally code from deploy.ps1 to retrieve artifacts for releases or builds - now as an action to read apps into a folder. 181 | 182 | ### New Workflows 183 | 184 | - **Pull PowerPlatform Changes** for pulling changes from your PowerPlatform development environment into your AL-Go for GitHub repository 185 | - **Push PowerPlatform Changes** for pushing changes from your AL-Go for GitHub repository to your PowerPlatform development environment 186 | 187 | > [!NOTE] 188 | > PowerPlatform workflows are only available in the PTE template and will be removed if no PowerPlatformSolutionFolder is defined in settings. 189 | 190 | ### New Scenarios (Documentation) 191 | 192 | - [Connect your GitHub repository to Power Platform](https://github.com/microsoft/AL-Go/blob/main/Scenarios/SetupPowerPlatform.md) 193 | - [How to set up Service Principal for Power Platform](https://github.com/microsoft/AL-Go/blob/main/Scenarios/SetupServicePrincipalForPowerPlatform.md) 194 | - [Try one of the Business Central and Power Platform samples](https://github.com/microsoft/AL-Go/blob/main/Scenarios/TryPowerPlatformSamples.md) 195 | - [Publish To AppSource](https://github.com/microsoft/AL-Go/blob/main/Scenarios/PublishToAppSource.md) 196 | 197 | > [!NOTE] 198 | > PowerPlatform functionality are only available in the PTE template. 199 | 200 | ## v5.1 201 | 202 | ### Issues 203 | 204 | - Issue 1019 CI/CD Workflow still being scheduled after it was disabled 205 | - Issue 1021 Error during Create Online Development Environment action 206 | - Issue 1022 Error querying artifacts: No such host is known. (bcartifacts-exdbf9fwegejdqak.blob.core.windows.net:443) 207 | - Issue 922 Deploy Reference Documentation (ALDoc) failed with custom 208 | - ContainerName used during build was invalid if project names contained special characters 209 | - Issue 1009 by adding a includeDependencies property in DeliverToAppSource 210 | - Issue 997 'Deliver to AppSource' action fails for projects containing a space 211 | - Issue 987 Resource not accessible by integration when creating release from specific version 212 | - Issue 979 Publish to AppSource Documentation 213 | - Issue 1018 Artifact setting - possibility to read version from app.json 214 | - Issue 1008 Allow PullRequestHandler to use ubuntu or self hosted runners for all jobs except for pregateCheck 215 | - Issue 962 Finer control of "shell"-property 216 | - Issue 1041 Harden the version comparison when incrementing version number 217 | - Issue 1042 Downloading artifacts from GitHub doesn't work with branch names which include forward slashes 218 | 219 | ### Better artifact selection 220 | 221 | The artifact setting in your project settings file can now contain a `*` instead of the version number. This means that AL-Go for GitHub will determine the application dependency for your projects together with the `applicationDependency` setting and determine which Business Central version is needed for the project. 222 | 223 | - `"artifact": "//*//latest"` will give you the latest Business Central version, higher than your application dependency and with the same major.minor as your application dependency. 224 | - `"artifact": "//*//first"` will give you the first Business Central version, higher than your application dependency and with the same major.minor as your application dependency. 225 | 226 | ### New Settings 227 | 228 | - `deliverToAppSource`: a JSON object containing the following properties 229 | - **productId** must be the product Id from partner Center. 230 | - **mainAppFolder** specifies the appFolder of the main app if you have multiple apps in the same project. 231 | - **continuousDelivery** can be set to true to enable continuous delivery of every successful build to AppSource Validation. Note that the app will only be in preview in AppSource and you will need to manually press GO LIVE in order for the app to be promoted to production. 232 | - **includeDependencies** can be set to an array of file names (incl. wildcards) which are the names of the dependencies to include in the AppSource submission. Note that you need to set `generateDependencyArtifact` in the project settings file to true in order to include dependencies. 233 | - Add `shell` as a property under `DeployTo` structure 234 | 235 | ### Deprecated Settings 236 | 237 | - `appSourceContinuousDelivery` is moved to the `deliverToAppSource` structure 238 | - `appSourceMainAppFolder` is moved to the `deliverToAppSource` structure 239 | - `appSourceProductId` is moved to the `deliverToAppSource` structure 240 | 241 | ### New parameter -clean on localdevenv and clouddevenv 242 | 243 | Adding -clean when running localdevenv or clouddevenv will create a clean development environment without compiling and publishing your apps. 244 | 245 | ## v5.0 246 | 247 | ### Issues 248 | 249 | - Issue 940 Publish to Environment is broken when specifying projects to publish 250 | - Issue 994 CI/CD ignores Deploy to GitHub Pages in private repositories 251 | 252 | ### New Settings 253 | 254 | - `UpdateALGoSystemFilesEnvironment`: The name of the environment that is referenced in job `UpdateALGoSystemFiles` in the _Update AL-Go System Files_ workflow. See [jobs.\.environment](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idenvironment) for more information. Currently, only setting the environment name is supported. 255 | 256 | ### Issues 257 | 258 | - Support release branches that start with releases/ 259 | - Issue 870 Improve Error Handling when CLI is missing 260 | - Issue 889 CreateRelease and IncrementVersionNumber workflow did not handle wild characters in `appFolders`, `testFolders` or `bcptTestFolders` settings. 261 | - Issue 973 Prerelease is not used for deployment 262 | 263 | ### Build modes 264 | 265 | AL-Go ships with Default, Translated and Clean mode out of the box. Now you can also define custom build modes in addition to the ones shipped with AL-Go. This allows you to define your own build modes, which can be used to build your apps in different ways. By default, a custom build mode will build the apps similarly to the Default mode but this behavior can be overridden in e.g. script overrides in your repository. 266 | 267 | ## v4.1 268 | 269 | ### New Settings 270 | 271 | - `templateSha`: The SHA of the version of AL-Go currently used 272 | 273 | ### New Actions 274 | 275 | - `DumpWorkflowInfo`: Dump information about running workflow 276 | - `Troubleshooting` : Run troubleshooting for repository 277 | 278 | ### Update AL-Go System Files 279 | 280 | Add another parameter when running Update AL-Go System Files, called downloadLatest, used to indicate whether to download latest version from template repository. Default value is true. 281 | If false, the templateSha repository setting is used to download specific AL-Go System Files when calculating new files. 282 | 283 | ### Issues 284 | 285 | - Issue 782 Exclude '.altestrunner/' from template .gitignore 286 | - Issue 823 Dependencies from prior build jobs are not included when using useProjectDependencies 287 | - App artifacts for version 'latest' are now fetched from the latest CICD run that completed and successfully built all the projects for the corresponding branch. 288 | - Issue 824 Utilize `useCompilerFolder` setting when creating an development environment for an AL-Go project. 289 | - Issue 828 and 825 display warnings for secrets, which might cause AL-Go for GitHub to malfunction 290 | 291 | ### New Settings 292 | 293 | - `alDoc` : JSON object with properties for the ALDoc reference document generation 294 | - **continuousDeployment** = Determines if reference documentation will be deployed continuously as part of CI/CD. You can run the **Deploy Reference Documentation** workflow to deploy manually or on a schedule. (Default false) 295 | - **deployToGitHubPages** = Determines whether or not the reference documentation site should be deployed to GitHub Pages for the repository. In order to deploy to GitHub Pages, GitHub Pages must be enabled and set to GitHub Actions. (Default true) 296 | - **maxReleases** = Maximum number of releases to include in the reference documentation. (Default 3) 297 | - **groupByProject** = Determines whether projects in multi-project repositories are used as folders in reference documentation 298 | - **includeProjects** = An array of projects to include in the reference documentation. (Default all) 299 | - **excludeProjects** = An array of projects to exclude in the reference documentation. (Default none)- 300 | - **header** = Header for the documentation site. (Default: Documentation for...) 301 | - **footer** = Footer for the documentation site. (Default: Made with...) 302 | - **defaultIndexMD** = Markdown for the landing page of the documentation site. (Default: Reference documentation...) 303 | - **defaultReleaseMD** = Markdown for the landing page of the release sites. (Default: Release reference documentation...) 304 | - *Note that in header, footer, defaultIndexMD and defaultReleaseMD you can use the following placeholders: {REPOSITORY}, {VERSION}, {INDEXTEMPLATERELATIVEPATH}, {RELEASENOTES}* 305 | 306 | ### New Workflows 307 | 308 | - **Deploy Reference Documentation** is a workflow, which you can invoke manually or on a schedule to generate and deploy reference documentation using the aldoc tool, using the ALDoc setting properties described above. 309 | - **Troubleshooting** is a workflow, which you can invoke manually to run troubleshooting on the repository and check for settings or secrets, containing illegal values. When creating issues on https://github.com/microsoft/AL-Go/issues, we might ask you to run the troubleshooter to help identify common problems. 310 | 311 | ### Support for ALDoc reference documentation tool 312 | 313 | ALDoc reference documentation tool is now supported for generating and deploying reference documentation for your projects either continuously or manually/scheduled. 314 | 315 | ## v4.0 316 | 317 | ### Removal of the InsiderSasToken 318 | 319 | As of October 1st 2023, Business Central insider builds are now publicly available. When creating local containers with the insider builds, you will have to accept the insider EULA (https://go.microsoft.com/fwlink/?linkid=2245051) in order to continue. 320 | 321 | AL-Go for GitHub allows you to build and test using insider builds without any explicit approval, but please note that the insider artifacts contains the insider Eula and you automatically accept this when using the builds. 322 | 323 | ### Issues 324 | 325 | - Issue 730 Support for external rulesets. 326 | - Issue 739 Workflow specific KeyVault settings doesn't work for localDevEnv 327 | - Using self-hosted runners while using Azure KeyVault for secrets or signing might fail with C:\\Modules doesn't exist 328 | - PullRequestHandler wasn't triggered if only .md files where changes. This lead to PRs which couldn't be merged if a PR status check was mandatory. 329 | - Artifacts names for PR Builds were using the merge branch instead of the head branch. 330 | 331 | ### New Settings 332 | 333 | - `enableExternalRulesets`: set this setting to true if you want to allow AL-Go to automatically download external references in rulesets. 334 | - `deliverTo`: is not really new, but has new properties and wasn't documented. The complete list of properties is here (note that some properties are deliveryTarget specific): 335 | - **Branches** = an array of branch patterns, which are allowed to deliver to this deliveryTarget. (Default [ "main" ]) 336 | - **CreateContainerIfNotExist** = *[Only for DeliverToStorage]* Create Blob Storage Container if it doesn't already exist. (Default false) 337 | 338 | ### Deployment 339 | 340 | Environment URL is now displayed underneath the environment being deployed to in the build summary. For Custom Deployment, the script can set the GitHub Output variable `environmentUrl` in order to show a custom URL. 341 | 342 | ## v3.3 343 | 344 | ### Issues 345 | 346 | - Issue 227 Feature request: Allow deployments with "Schema Sync Mode" = Force 347 | - Issue 519 Deploying to onprem environment 348 | - Issue 520 Automatic deployment to environment with annotation 349 | - Issue 592 Internal Server Error when publishing 350 | - Issue 557 Deployment step fails when retried 351 | - After configuring deployment branches for an environment in GitHub and setting Deployment Branch Policy to **Protected Branches**, AL-Go for GitHub would fail during initialization (trying to get environments for deployment) 352 | - The DetermineDeploymentEnvironments doesn't work in private repositories (needs the GITHUB_TOKEN) 353 | - Issue 683 Settings from GitHub variables ALGoRepoSettings and ALGoOrgSettings are not applied during build pipeline 354 | - Issue 708 Inconsistent AuthTokenSecret Behavior in Multiple Projects: 'Secrets are not available' 355 | 356 | ### Breaking changes 357 | 358 | Earlier, you could specify a mapping to an environment name in an environment secret called `_EnvironmentName`, `-EnvironmentName` or just `EnvironmentName`. You could also specify the projects you want to deploy to an environment as an environment secret called `Projects`. 359 | 360 | This mechanism is no longer supported and you will get an error if your repository has these secrets. Instead you should use the `DeployTo` setting described below. 361 | 362 | Earlier, you could also specify the projects you want to deploy to an environment in a setting called `_Projects` or `-Projects`. This is also no longer supported. Instead use the `DeployTo` and remove the old settings. 363 | 364 | ### New Actions 365 | 366 | - `DetermineDeliveryTargets`: Determine which delivery targets should be used for delivering artifacts from the build job. 367 | - `DetermineDeploymentEnvironments`: Determine which deployment environments should be used for the workflow. 368 | 369 | ### New Settings 370 | 371 | - `projectName`: project setting used as friendly name for an AL-Go project, to be used in the UI for various workflows, e.g. CICD, Pull Request Build. 372 | - `fullBuildPatterns`: used by `DetermineProjectsToBuild` action to specify changes in which files and folders would trigger a full build (building all AL-Go projects). 373 | - `excludeEnvironments`: used by `DetermineDeploymentEnvironments` action to exclude environments from the list of environments considered for deployment. 374 | - `deployTo`: is not really new, but has new properties. The complete list of properties is here: 375 | - **EnvironmentType** = specifies the type of environment. The environment type can be used to invoke a custom deployment. (Default SaaS) 376 | - **EnvironmentName** = specifies the "real" name of the environment if it differs from the GitHub environment 377 | - **Branches** = an array of branch patterns, which are allowed to deploy to this environment. (Default [ "main" ]) 378 | - **Projects** = In multi-project repositories, this property can be a comma separated list of project patterns to deploy to this environment. (Default \*) 379 | - **SyncMode** = ForceSync if deployment to this environment should happen with ForceSync, else Add. If deploying to the development endpoint you can also specify Development or Clean. (Default Add) 380 | - **ContinuousDeployment** = true if this environment should be used for continuous deployment, else false. (Default: AL-Go will continuously deploy to sandbox environments or environments, which doesn't end in (PROD) or (FAT) 381 | - **runs-on** = specifies which GitHub runner to use when deploying to this environment. (Default is settings.runs-on) 382 | 383 | ### Custom Deployment 384 | 385 | By specifying a custom EnvironmentType in the DeployTo structure for an environment, you can now add a script in the .github folder called `DeployTo.ps1`. This script will be executed instead of the standard deployment mechanism with the following parameters in a HashTable: 386 | 387 | | Parameter | Description | Example | 388 | | --------- | :--- | :--- | 389 | | `$parameters.type` | Type of delivery (CD or Release) | CD | 390 | | `$parameters.apps` | Apps to deploy | /home/runner/.../GHP-Common-main-Apps-2.0.33.0.zip | 391 | | `$parameters.EnvironmentType` | Environment type | SaaS | 392 | | `$parameters.EnvironmentName` | Environment name | Production | 393 | | `$parameters.Branches` | Branches which should deploy to this environment (from settings) | main,dev | 394 | | `$parameters.AuthContext` | AuthContext in a compressed Json structure | {"refreshToken":"mytoken"} | 395 | | `$parameters.BranchesFromPolicy` | Branches which should deploy to this environment (from GitHub environments) | main | 396 | | `$parameters.Projects` | Projects to deploy to this environment | | 397 | | `$parameters.ContinuousDeployment` | Is this environment setup for continuous deployment | false | 398 | | `$parameters."runs-on"` | GitHub runner to be used to run the deployment script | windows-latest | 399 | 400 | ### Status Checks in Pull Requests 401 | 402 | AL-Go for GitHub now adds status checks to Pull Requests Builds. In your GitHub branch protection rules, you can set up "Pull Request Status Check" to be a required status check to ensure Pull Request Builds succeed before merging. 403 | 404 | ### Secrets in AL-Go for GitHub 405 | 406 | In v3.2 of AL-Go for GitHub, all secrets requested by AL-Go for GitHub were available to all steps in a job one compressed JSON structure in env:Secrets. 407 | With this update, only the steps that actually requires secrets will have the secrets available. 408 | 409 | ## v3.2 410 | 411 | ### Issues 412 | 413 | Issue 542 Deploy Workflow fails 414 | Issue 558 CI/CD attempts to deploy from feature branch 415 | Issue 559 Changelog includes wrong commits 416 | Publish to AppSource fails if publisher name or app name contains national or special characters 417 | Issue 598 Cleanup during flush if build pipeline doesn't cleanup properly 418 | Issue 608 When creating a release, throw error if no new artifacts have been added 419 | Issue 528 Give better error messages when uploading to storage accounts 420 | Create Online Development environment workflow failed in AppSource template unless AppSourceCopMandatoryAffixes is defined in repository settings file 421 | Create Online Development environment workflow didn't have a project parameter and only worked for single project repositories 422 | Create Online Development environment workflow didn't work if runs-on was set to Linux 423 | Special characters are not supported in RepoName, Project names or other settings - Use UTF8 encoding to handle special characters in GITHUB_OUTPUT and GITHUB_ENV 424 | 425 | ### Issue 555 426 | 427 | AL-Go contains several workflows, which create a Pull Request or pushes code directly. 428 | All (except Update AL-Go System Files) earlier used the GITHUB_TOKEN to create the PR or commit. 429 | The problem using GITHUB_TOKEN is that is doesn't trigger a pull request build or a commit build. 430 | This is by design: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow 431 | Now, you can set the checkbox called Use GhTokenWorkflow to allowing you to use the GhTokenWorkflow instead of the GITHUB_TOKEN - making sure that workflows are triggered 432 | 433 | ### New Settings 434 | 435 | - `keyVaultCodesignCertificateName`: With this setting you can delegate the codesigning to an Azure Key Vault. This can be useful if your certificate has to be stored in a Hardware Security Module 436 | - `PullRequestTrigger`: With this setting you can set which trigger to use for Pull Request Builds. By default AL-Go will use pull_request_target. 437 | 438 | ### New Actions 439 | 440 | - `DownloadProjectDependencies`: Downloads the dependency apps for a given project and build mode. 441 | 442 | ### Settings and Secrets in AL-Go for GitHub 443 | 444 | In earlier versions of AL-Go for GitHub, all settings were available as individual environment variables to scripts and overrides, this is no longer the case. 445 | Settings were also available as one compressed JSON structure in env:Settings, this is still the case. 446 | Settings can no longer contain line breaks. It might have been possible to use line breaks earlier, but it would likely have unwanted consequences. 447 | Use `$settings = $ENV:Settings | ConvertFrom-Json` to get all settings in PowerShell. 448 | 449 | In earlier versions of AL-Go for GitHub, all secrets requested by AL-Go for GitHub were available as individual environment variables to scripts and overrides, this is no longer the case. 450 | As described in bug 647, all secrets available to the workflow were also available in env:\_Secrets, this is no longer the case. 451 | All requested secrets were also available (base64 encoded) as one compressed JSON structure in env:Secrets, this is still the case. 452 | Use `$secrets = $ENV:Secrets | ConvertFrom-Json` to get all requested secrets in PowerShell. 453 | You cannot get to any secrets that weren't requested by AL-Go for GitHub. 454 | 455 | ## v3.1 456 | 457 | ### Issues 458 | 459 | Issue #446 Wrong NewLine character in Release Notes 460 | Issue #453 DeliverToStorage - override fails reading secrets 461 | Issue #434 Use gh auth token to get authentication token instead of gh auth status 462 | Issue #501 The Create New App action will now use 22.0.0.0 as default application reference and include NoImplicitwith feature. 463 | 464 | ### New behavior 465 | 466 | The following workflows: 467 | 468 | - Create New App 469 | - Create New Test App 470 | - Create New Performance Test App 471 | - Increment Version Number 472 | - Add Existing App 473 | - Create Online Development Environment 474 | 475 | All these actions now uses the selected branch in the **Run workflow** dialog as the target for the Pull Request or Direct COMMIT. 476 | 477 | ### New Settings 478 | 479 | - `UseCompilerFolder`: Setting useCompilerFolder to true causes your pipelines to use containerless compiling. Unless you also set `doNotPublishApps` to true, setting useCompilerFolder to true won't give you any performance advantage, since AL-Go for GitHub will still need to create a container in order to publish and test the apps. In the future, publishing and testing will be split from building and there will be other options for getting an instance of Business Central for publishing and testing. 480 | - `vsixFile`: vsixFile should be a direct download URL to the version of the AL Language extension you want to use for building the project or repo. By default, AL-Go will use the AL Language extension that comes with the Business Central Artifacts. 481 | 482 | ### New Workflows 483 | 484 | - **\_BuildALGoProject** is a reusable workflow that unites the steps for building an AL-Go projects. It has been reused in the following workflows: _CI/CD_, _Pull Request Build_, _NextMinor_, _NextMajor_ and _Current_. 485 | The workflow appears under the _Actions_ tab in GitHub, but it is not actionable in any way. 486 | 487 | ### New Actions 488 | 489 | - **DetermineArtifactUrl** is used to determine which artifacts to use for building a project in CI/CD, PullRequestHandler, Current, NextMinor and NextMajor workflows. 490 | 491 | ### License File 492 | 493 | With the changes to the CRONUS license in Business Central version 22, that license can in most cases be used as a developer license for AppSource Apps and it is no longer mandatory to specify a license file in AppSource App repositories. 494 | Obviously, if you build and test your app for Business Central versions prior to 21, it will fail if you don't specify a licenseFileUrl secret. 495 | 496 | ## v3.0 497 | 498 | ### **NOTE:** When upgrading to this version 499 | 500 | When upgrading to this version form earlier versions of AL-Go for GitHub, you will need to run the _Update AL-Go System Files_ workflow twice if you have the `useProjectDependencies` setting set to _true_. 501 | 502 | ### Publish to unknown environment 503 | 504 | You can now run the **Publish To Environment** workflow without creating the environment in GitHub or settings up-front, just by specifying the name of a single environment in the Environment Name when running the workflow. 505 | Subsequently, if an AuthContext secret hasn't been created for this environment, the Device Code flow authentication will be initiated from the Publish To Environment workflow and you can publish to the new environment without ever creating a secret. 506 | Open Workflow details to get the device Code for authentication in the job summary for the initialize job. 507 | 508 | ### Create Online Dev. Environment 509 | 510 | When running the **Create Online Dev. Environment** workflow without having the _adminCenterApiCredentials_ secret created, the workflow will intiate the deviceCode flow and allow you to authenticate to the Business Central Admin Center. 511 | Open Workflow details to get the device Code for authentication in the job summary for the initialize job. 512 | 513 | ### Issues 514 | 515 | - Issue #391 Create release action - CreateReleaseBranch error 516 | - Issue 434 Building local DevEnv, downloading dependencies: Authentication fails when using "gh auth status" 517 | 518 | ### Changes to Pull Request Process 519 | 520 | In v2.4 and earlier, the PullRequestHandler would trigger the CI/CD workflow to run the PR build. 521 | Now, the PullRequestHandler will perform the build and the CI/CD workflow is only run on push (or manual dispatch) and will perform a complete build. 522 | 523 | ### Build modes per project 524 | 525 | Build modes can now be specified per project 526 | 527 | ### New Actions 528 | 529 | - **DetermineProjectsToBuild** is used to determine which projects to build in PullRequestHandler, CI/CD, Current, NextMinor and NextMajor workflows. 530 | - **CalculateArtifactNames** is used to calculate artifact names in PullRequestHandler, CI/CD, Current, NextMinor and NextMajor workflows. 531 | - **VerifyPRChanges** is used to verify whether a PR contains changes, which are not allowed from a fork. 532 | 533 | ## v2.4 534 | 535 | ### Issues 536 | 537 | - Issue #171 create a workspace file when creating a project 538 | - Issue #356 Publish to AppSource fails in multi project repo 539 | - Issue #358 Publish To Environment Action stopped working in v2.3 540 | - Issue #362 Support for EnableTaskScheduler 541 | - Issue #360 Creating a release and deploying from a release branch 542 | - Issue #371 'No previous release found' for builds on release branches 543 | - Issue #376 CICD jobs that are triggered by the pull request trigger run directly to an error if title contains quotes 544 | 545 | ### Release Branches 546 | 547 | **NOTE:** Release Branches are now only named after major.minor if the patch value is 0 in the release tag (which must be semver compatible) 548 | 549 | This version contains a number of bug fixes to release branches, to ensure that the recommended branching strategy is fully supported. Bugs fixed includes: 550 | 551 | - Release branches was named after the full tag (1.0.0), even though subsequent hotfixes released from this branch would be 1.0.x 552 | - Release branches named 1.0 wasn't picked up as a release branch 553 | - Release notes contained the wrong changelog 554 | - The previous release was always set to be the first release from a release branch 555 | - SemVerStr could not have 5 segments after the dash 556 | - Release was created on the right SHA, but the release branch was created on the wrong SHA 557 | 558 | Recommended branching strategy: 559 | 560 | ![Branching Strategy](https://raw.githubusercontent.com/microsoft/AL-Go/main/Scenarios/images/branchingstrategy.png) 561 | 562 | ### New Settings 563 | 564 | New Project setting: EnableTaskScheduler in container executing tests and when setting up local development environment 565 | 566 | ### Support for GitHub variables: ALGoOrgSettings and ALGoRepoSettings 567 | 568 | Recently, GitHub added support for variables, which you can define on your organization or your repository. 569 | AL-Go now supports that you can define a GitHub variable called ALGoOrgSettings, which will work for all repositories (with access to the variable) 570 | Org Settings will be applied before Repo settings and local repository settings files will override values in the org settings 571 | You can also define a variable called ALGoRepoSettings on the repository, which will be applied after reading the Repo Settings file in the repo 572 | Example for usage could be setup of branching strategies, versioning or an appDependencyProbingPaths to repositories which all repositories share. 573 | appDependencyProbingPaths from settings variables are merged together with appDependencyProbingPaths defined in repositories 574 | 575 | ### Refactoring and tests 576 | 577 | ReadSettings has been refactored to allow organization wide settings to be added as well. CI Tests have been added to cover ReadSettings. 578 | 579 | ## v2.3 580 | 581 | ### Issues 582 | 583 | - Issue #312 Branching enhancements 584 | - Issue #229 Create Release action tags wrong commit 585 | - Issue #283 Create Release workflow uses deprecated actions 586 | - Issue #319 Support for AssignPremiumPlan 587 | - Issue #328 Allow multiple projects in AppSource App repo 588 | - Issue #344 Deliver To AppSource on finding app.json for the app 589 | - Issue #345 LocalDevEnv.ps1 can't Dowload the file license file 590 | 591 | ### New Settings 592 | 593 | New Project setting: AssignPremiumPlan on user in container executing tests and when setting up local development environment 594 | New Repo setting: unusedALGoSystemFiles is an array of AL-Go System Files, which won't be updated during Update AL-Go System Files. They will instead be removed. Use with care, as this can break the AL-Go for GitHub functionality and potentially leave your repo no longer functional. 595 | 596 | ### Build modes support 597 | 598 | AL-Go projects can now be built in different modes, by specifying the _buildModes_ setting in AL-Go-Settings.json. Read more about build modes in the [Basic Repository settings](https://github.com/microsoft/AL-Go/blob/main/Scenarios/settings.md#basic-repository-settings). 599 | 600 | ### LocalDevEnv / CloudDevEnv 601 | 602 | With the support for PowerShell 7 in BcContainerHelper, the scripts LocalDevEnv and CloudDevEnv (placed in the .AL-Go folder) for creating development environments have been modified to run inside VS Code instead of spawning a new powershell 5.1 session. 603 | 604 | ### Continuous Delivery 605 | 606 | Continuous Delivery can now run from other branches than main. By specifying a property called branches, containing an array of branches in the deliveryContext json construct, the artifacts generated from this branch are also delivered. The branch specification can include wildcards (like release/\*). Default is main, i.e. no changes to functionality. 607 | 608 | ### Continuous Deployment 609 | 610 | Continuous Deployment can now run from other branches than main. By creating a repo setting (.github/AL-Go-Settings.json) called **`-Branches`**, which is an array of branches, which will deploy the generated artifacts to this environment. The branch specification can include wildcards (like release/\*), although this probably won't be used a lot in continuous deployment. Default is main, i.e. no changes to functionality. 611 | 612 | ### Create Release 613 | 614 | When locating artifacts for the various projects, the SHA used to build the artifact is used for the release tag 615 | If all projects are not available with the same SHA, this error is thrown: **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.** 616 | There is no longer a hard dependency on the main branch name from Create Release. 617 | 618 | ### AL-Go Tests 619 | 620 | Some unit tests have been added and AL-Go unit tests can now be run directly from VS Code. 621 | Another set of end to end tests have also been added and in the documentation on contributing to AL-Go, you can see how to run these in a local fork or from VS Code. 622 | 623 | ### LF, UTF8 and JSON 624 | 625 | GitHub natively uses LF as line seperator in source files. 626 | In earlier versions of AL-Go for GitHub, many scripts and actions would use CRLF and convert back and forth. Some files were written with UTF8 BOM (Byte Order Mark), other files without and JSON formatting was done using PowerShell 5.1 (which is different from PowerShell 7). 627 | In the latest version, we always use LF as line seperator, UTF8 without BOM and JSON files are written using PowerShell 7. If you have self-hosted runners, you need to ensure that PS7 is installed to make this work. 628 | 629 | ### Experimental Support 630 | 631 | Setting the repo setting "shell" to "pwsh", followed by running Update AL-Go System Files, will cause all PowerShell code to be run using PowerShell 7 instead of PowerShell 5. This functionality is experimental. Please report any issues at https://github.com/microsoft/AL-Go/issues 632 | Setting the repo setting "runs-on" to "Ubuntu-Latest", followed by running Update AL-Go System Files, will cause all non-build jobs to run using Linux. This functionality is experimental. Please report any issues at https://github.com/microsoft/AL-Go/issues 633 | 634 | ## v2.2 635 | 636 | ### Enhancements 637 | 638 | - Container Event log is added as a build artifact if builds or tests are failing 639 | 640 | ### Issues 641 | 642 | - Issue #280 Overflow error when test result summary was too big 643 | - Issue #282, 292 AL-Go for GitHub causes GitHub to issue warnings 644 | - Issue #273 Potential security issue in Pull Request Handler in Open Source repositories 645 | - Issue #303 PullRequestHandler fails on added files 646 | - Issue #299 Multi-project repositories build all projects on Pull Requests 647 | - Issue #291 Issues with new Pull Request Handler 648 | - Issue #287 AL-Go pipeline fails in ReadSettings step 649 | 650 | ### Changes 651 | 652 | - VersioningStrategy 1 is no longer supported. GITHUB_ID has changed behavior (Issue #277) 653 | 654 | ## v2.1 655 | 656 | ### Issues 657 | 658 | - Issue #233 AL-Go for GitHub causes GitHub to issue warnings 659 | - Issue #244 Give error if AZURE_CREDENTIALS contains line breaks 660 | 661 | ### Changes 662 | 663 | - New workflow: PullRequestHandler to handle all Pull Requests and pass control safely to CI/CD 664 | - Changes to yaml files, PowerShell scripts and codeowners files are not permitted from fork Pull Requests 665 | - Test Results summary (and failed tests) are now displayed directly in the CI/CD workflow and in the Pull Request Check 666 | 667 | ### Continuous Delivery 668 | 669 | - Proof Of Concept Delivery to GitHub Packages and Nuget 670 | 671 | ## v2.0 672 | 673 | ### Issues 674 | 675 | - Issue #143 Commit Message for **Increment Version Number** workflow 676 | - Issue #160 Create local DevEnv aith appDependencyProbingPaths 677 | - Issue #156 Versioningstrategy 2 doesn't use 24h format 678 | - Issue #155 Initial Add existing app fails with "Cannot find path" 679 | - Issue #152 Error when loading dependencies from releases 680 | - Issue #168 Regression in preview fixed 681 | - Issue #189 Warnings: Resource not accessible by integration 682 | - Issue #190 PublishToEnvironment is not working with AL-Go-PTE@preview 683 | - Issue #186 AL-GO build fails for multi-project repository when there's nothing to build 684 | - When you have GitHub pages enabled, AL-Go for GitHub would try to publish to github_pages environment 685 | - Special characters wasn't supported in parameters to GitHub actions (Create New App etc.) 686 | 687 | ### Continuous Delivery 688 | 689 | - Added new GitHub Action "Deliver" to deliver build output to Storage or AppSource 690 | - Refactor CI/CD and Release workflows to use new deliver action 691 | - Custom delivery supported by creating scripts with the naming convention DeliverTo\*.ps1 in the .github folder 692 | 693 | ### AppSource Apps 694 | 695 | - New workflow: Publish to AppSource 696 | - Continuous Delivery to AppSource validation supported 697 | 698 | ### Settings 699 | 700 | - New Repo setting: CICDPushBranches can be specified as an array of branches, which triggers a CI/CD workflow on commit. Default is main', release/\*, feature/\* 701 | - New Repo setting: CICDPullRequestBranches can be specified as an array of branches, which triggers a CI/CD workflow on pull request. Default is main 702 | - New Repo setting: CICDSchedule can specify a CRONTab on when you want to run CI/CD on a schedule. Note that this will disable Push and Pull Request triggers unless specified specifically using CICDPushBranches or CICDPullRequestBranches 703 | - New Repo setting: UpdateGitHubGoSystemFilesSchedule can specify a CRONTab on when you want to Update AL-Go System Files. Note that when running on a schedule, update AL-Go system files will perfom a direct commit and not create a pull request. 704 | - New project Setting: AppSourceContext should be a compressed json structure containing authContext for submitting to AppSource. The BcContainerHelperFunction New-ALGoAppSourceContext will help you create this structure. 705 | - New project Setting: AppSourceContinuousDelivery. Set this to true in enable continuous delivery for this project to AppSource. This requires AppSourceContext and AppSourceProductId to be set as well 706 | - New project Setting: AppSourceProductId should be set to the product Id of this project in AppSource 707 | - New project Setting: AppSourceMainAppFolder. If you have multiple appFolders, this is the folder name of the main app to submit to AppSource. 708 | 709 | ### All workflows 710 | 711 | - Support 2 folder levels projects (apps\\w1, apps\\dk etc.) 712 | - Better error messages for if an error occurs within an action 713 | - Special characters are now supported in secrets 714 | - Initial support for agents running inside containers on a host 715 | - Optimized workflows to have fewer jobs 716 | 717 | ### Update AL-Go System Files Workflow 718 | 719 | - workflow now displays the currently used template URL when selecting the Run Workflow action 720 | 721 | ### CI/CD workflow 722 | 723 | - Better detection of changed projects 724 | - appDependencyProbingPaths did not support multiple projects in the same repository for latestBuild dependencies 725 | - appDependencyProbingPaths with release=latestBuild only considered the last 30 artifacts 726 | - Use mutex around ReadSecrets to ensure that multiple agents on the same host doesn't clash 727 | - Add lfs when checking out files for CI/CD to support checking in dependencies 728 | - Continue on error with Deploy and Deliver 729 | 730 | ### CI/CD and Publish To New Environment 731 | 732 | - Base functionality for selecting a specific GitHub runner for an environment 733 | - Include dependencies artifacts when deploying (if generateDependencyArtifact is true) 734 | 735 | ### localDevEnv.ps1 and cloudDevEnv.ps1 736 | 737 | - Display clear error message if something goes wrong 738 | 739 | ## v1.5 740 | 741 | ### Issues 742 | 743 | - Issue #100 - Add more resilience to localDevEnv.ps1 and cloudDevEnv.ps1 744 | - Issue #131 - Special characters are not allowed in secrets 745 | 746 | ### All workflows 747 | 748 | - During initialize, all AL-Go settings files are now checked for validity and reported correctly 749 | - During initialize, the version number of AL-Go for GitHub is printed in large letters (incl. preview or dev.) 750 | 751 | ### New workflow: Create new Performance Test App 752 | 753 | - Create BCPT Test app and add to bcptTestFolders to run bcpt Tests in workflows (set doNotRunBcptTests in workflow settings for workflows where you do NOT want this) 754 | 755 | ### Update AL-Go System Files Workflow 756 | 757 | - Include release notes of new version in the description of the PR (and in the workflow output) 758 | 759 | ### CI/CD workflow 760 | 761 | - Apps are not signed when the workflow is running as a Pull Request validation 762 | - if a secret called applicationInsightsConnectionString exists, then the value of that will be used as ApplicationInsightsConnectionString for the app 763 | 764 | ### Increment Version Number Workflow 765 | 766 | - Bugfix: increment all apps using f.ex. +0.1 would fail. 767 | 768 | ### Environments 769 | 770 | - Add suport for EnvironmentName redirection by adding an Environment Secret under the environment or a repo secret called \\_EnvironmentName with the actual environment name. 771 | - No default environment name on Publish To Environment 772 | - For multi-project repositories, you can specify an environment secret called Projects or a repo setting called \\_Projects, containing the projects you want to deploy to this environment. 773 | 774 | ### Settings 775 | 776 | - New setting: **runs-on** to allow modifying runs-on for all jobs (requires Update AL-Go System files after changing the setting) 777 | - New setting: **DoNotSignApps** - setting this to true causes signing of the app to be skipped 778 | - New setting: **DoNotPublishApps** - setting this to true causes the workflow to skip publishing, upgrading and testing the app to improve performance. 779 | - New setting: **ConditionalSettings** to allow to use different settings for specific branches. Example: 780 | 781 | ``` 782 | "ConditionalSettings": [ 783 | { 784 | "branches": [ 785 | "feature/*" 786 | ], 787 | "settings": { 788 | "doNotPublishApps": true, 789 | "doNotSignApps": true 790 | } 791 | } 792 | ] 793 | ``` 794 | 795 | - Default **BcContainerHelperVersion** is now based on AL-Go version. Preview AL-Go selects preview bcContainerHelper, normal selects latest. 796 | - New Setting: **bcptTestFolders** contains folders with BCPT tests, which will run in all build workflows 797 | - New Setting: set **doNotRunBcptTest** to true (in workflow specific settings file?) to avoid running BCPT tests 798 | - New Setting: set **obsoleteTagMinAllowedMajorMinor** to enable appsource cop to validate your app against future changes (AS0105). This setting will become auto-calculated in Test Current, Test Next Minor and Test Next Major later. 799 | 800 | ## v1.4 801 | 802 | ### All workflows 803 | 804 | - Add requested permissions to avoid dependency on user/org defaults being too permissive 805 | 806 | ### Update AL-Go System Files Workflow 807 | 808 | - Default host to https://github.com/ (you can enter **myaccount/AL-Go-PTE@main** to change template) 809 | - Support for "just" changing branch (ex. **@Preview**) to shift to the preview version 810 | 811 | ### CI/CD Workflow 812 | 813 | - Support for feature branches (naming **feature/\***) - CI/CD workflow will run, but not generate artifacts nor deploy to QA 814 | 815 | ### Create Release Workflow 816 | 817 | - Support for release branches 818 | - Force Semver format on release tags 819 | - Add support for creating release branches on release (naming release/\*) 820 | - Add support for incrementing main branch after release 821 | 822 | ### Increment version number workflow 823 | 824 | - Add support for incremental (and absolute) version number change 825 | 826 | ### Environments 827 | 828 | - Support environmentName redirection in CI/CD and Publish To Environments workflows 829 | - If the name in Environments or environments settings doesn't match the actual environment name, 830 | - You can add a secret called EnvironmentName under the environment (or \\_ENVIRONMENTNAME globally) 831 | 832 | ## v1.3 833 | 834 | ### Issues 835 | 836 | - Issue #90 - Environments did not work. Secrets for environments specified in settings can now be **\\_AUTHCONTEXT** 837 | 838 | ### CI/CD Workflow 839 | 840 | - Give warning instead of error If no artifacts are found in **appDependencyProbingPaths** 841 | 842 | ## v1.2 843 | 844 | ### Issues 845 | 846 | - Issue #90 - Environments did not work. Environments (even if only defined in the settings file) did not work for private repositories if you didn't have a premium subscription. 847 | 848 | ### Local scripts 849 | 850 | - **LocalDevEnv.ps1** and \***CloudDevEnv.ps1** will now spawn a new PowerShell window as admin instead of running inside VS Code. Normally people doesn't run VS Code as administrator, and they shouldn't have to. Furthermore, I have seen a some people having problems when running these scripts inside VS Code. 851 | 852 | ## v1.1 853 | 854 | ### Settings 855 | 856 | - New Repo Setting: **GenerateDependencyArtifact** (default **false**). When true, CI/CD pipeline generates an artifact with the external dependencies used for building the apps in this repo. 857 | - New Repo Setting: **UpdateDependencies** (default **false**). When true, the default artifact for building the apps in this repo is not the latest available artifacts for this country, but instead the first compatible version (after calculating application dependencies). It is recommended to run Test Current, Test NextMinor and Test NextMajor in order to test your app against current and future builds. 858 | 859 | ### CI/CD Workflow 860 | 861 | - New Artifact: BuildOutput.txt. All compiler warnings and errors are emitted to this file to make it easier to investigate compiler errors and build a better UI for build errors and test results going forward. 862 | - TestResults artifact name to include repo version number and workflow name (for Current, NextMinor and NextMajor) 863 | - Default dependency version in appDependencyProbingPaths setting used is now latest Release instead of LatestBuild 864 | --------------------------------------------------------------------------------