diff --git a/Actions/AL-Go-Helper.ps1 b/Actions/AL-Go-Helper.ps1 index d878b873..b72361d5 100644 --- a/Actions/AL-Go-Helper.ps1 +++ b/Actions/AL-Go-Helper.ps1 @@ -369,20 +369,21 @@ function ReadSettings { "keyVaultClientIdSecretName" = "" "codeSignCertificateUrlSecretName" = "CodeSignCertificateUrl" "codeSignCertificatePasswordSecretName" = "CodeSignCertificatePassword" - "supportedCountries" = @() + "additionalCountries" = @() "appDependencies" = @() "appFolders" = @() "testDependencies" = @() "testFolders" = @() "installApps" = @() "installTestApps" = @() - "applicationDependency" = "19.0.0.0" + "applicationDependency" = "18.0.0.0" "installTestRunner" = $false "installTestFramework" = $false "installTestLibraries" = $false "installPerformanceToolkit" = $false "enableCodeCop" = $false "enableUICop" = $false + "customCodeCops" = @() "doNotBuildTests" = $false "doNotRunTests" = $false "appSourceCopMandatoryAffixes" = @() @@ -391,15 +392,17 @@ function ReadSettings { "templateBranch" = "" "appDependencyProbingPaths" = @() "githubRunner" = "windows-latest" + "cacheImageName" = "my" "alwaysBuildAllProjects" = $false "MicrosoftTelemetryConnectionString" = $MicrosoftTelemetryConnectionString "PartnerTelemetryConnectionString" = "" "SendExtendedTelemetryToMicrosoft" = $false } - $RepoSettingsFile, $ALGoSettingsFile, (Join-Path $ALGoFolder "$workflowName.setting.json"), (Join-Path $ALGoFolder "$userName.settings.json") | ForEach-Object { + $RepoSettingsFile, $ALGoSettingsFile, (Join-Path $ALGoFolder "$workflowName.settings.json"), (Join-Path $ALGoFolder "$userName.settings.json") | ForEach-Object { $settingsFile = $_ $settingsPath = Join-Path $baseFolder $settingsFile + Write-Host "Checking $settingsFile" if (Test-Path $settingsPath) { try { Write-Host "Reading $settingsFile" @@ -491,29 +494,33 @@ function AnalyzeRepo { throw "No artifacts found for the artifact setting ($artifact) in $ALGoSettingsFile" } $version = $artifactUrl.Split('/')[4] + $storageAccount = $artifactUrl.Split('/')[2] } - if ($settings.supportedCountries -or $country -ne $settings.country) { + if ($settings.additionalCountries -or $country -ne $settings.country) { if ($country -ne $settings.country) { OutputWarning -message "artifact definition in $ALGoSettingsFile uses a different country ($country) than the country definition ($($settings.country))" } - Write-Host "Checking Country and SupportedCountries" + Write-Host "Checking Country and additionalCountries" # AT is the latest published language - use this to determine available country codes (combined with mapping) $ver = [Version]$version Write-Host "https://$storageAccount/$artifactType/$version/$country" $atArtifactUrl = Get-BCArtifactUrl -storageAccount $storageAccount -type $artifactType -country at -version "$($ver.Major).$($ver.Minor)" -select Latest -sasToken $sasToken Write-Host "Latest AT artifacts $atArtifactUrl" $latestATversion = $atArtifactUrl.Split('/')[4] - $countries = Get-BCArtifactUrl -storageAccount $storageAccount -type $artifactType -version $latestATversion -sasToken $sasToken -select All | ForEach-Object { $_.Split('/')[5] } + $countries = Get-BCArtifactUrl -storageAccount $storageAccount -type $artifactType -version $latestATversion -sasToken $sasToken -select All | ForEach-Object { + $countryArtifactUrl = $_.Split('?')[0] # remove sas token + $countryArtifactUrl.Split('/')[5] # get country + } Write-Host "Countries with artifacts $($countries -join ',')" $allowedCountries = $bcContainerHelperConfig.mapCountryCode.PSObject.Properties.Name + $countries | Select-Object -Unique Write-Host "Allowed Country codes $($allowedCountries -join ',')" if ($allowedCountries -notcontains $settings.country) { throw "Country ($($settings.country)), specified in $ALGoSettingsFile is not a valid country code." } - $illegalCountries = $settings.supportedCountries | Where-Object { $allowedCountries -notcontains $_ } + $illegalCountries = $settings.additionalCountries | Where-Object { $allowedCountries -notcontains $_ } if ($illegalCountries) { - throw "SupportedCountries contains one or more invalid country codes ($($illegalCountries -join ",")) in $ALGoSettingsFile." + throw "additionalCountries contains one or more invalid country codes ($($illegalCountries -join ",")) in $ALGoSettingsFile." } } else { @@ -606,7 +613,7 @@ function AnalyzeRepo { $settings.appDependencies + $settings.testDependencies | ForEach-Object { $dep = $_ if ($dep -is [string]) { - # TODO: handle pre-settings + # TODO: handle pre-settings - documentation pending } } @@ -1144,12 +1151,12 @@ function CreateDevEnv { -enableAppSourceCop:$repo.enableAppSourceCop ` -enablePerTenantExtensionCop:$repo.enablePerTenantExtensionCop ` -enableUICop:$repo.enableUICop ` + -customCodeCops:$repo.customCodeCops ` -azureDevOps:($caller -eq 'AzureDevOps') ` -gitLab:($caller -eq 'GitLab') ` -gitHubActions:($caller -eq 'GitHubActions') ` -failOn 'error' ` -AppSourceCopMandatoryAffixes $repo.appSourceCopMandatoryAffixes ` - -AppSourceCopSupportedCountries @() ` -doNotRunTests ` -useDevEndpoint ` -keepContainer diff --git a/Actions/CheckForUpdates/CheckForUpdates.ps1 b/Actions/CheckForUpdates/CheckForUpdates.ps1 index 803cc788..52d21127 100644 --- a/Actions/CheckForUpdates/CheckForUpdates.ps1 +++ b/Actions/CheckForUpdates/CheckForUpdates.ps1 @@ -116,6 +116,7 @@ try { Get-ChildItem -Path $srcFolder -Filter $_.pattern | ForEach-Object { $srcFile = $_.FullName $fileName = $_.Name + $baseName = $_.BaseName $srcContent = (Get-Content -Path $srcFile -Encoding UTF8 -Raw).Replace("`r", "").Replace("`n", "`r`n") $name = $type if ($type -eq "workflow") { @@ -123,19 +124,27 @@ try { if ($_ -match '^name:([^#]*)(#.*$|$)') { $name = "workflow '$($Matches[1].Trim())'" } } } + + $workflowScheduleKey = "$($baseName)Schedule" + if ($repoSettings.ContainsKey($workflowScheduleKey)) { + $srcPattern = "on:`r`n workflow_dispatch:`r`n" + $replacePattern = "on:`r`n schedule:`r`n - cron: '$($repoSettings."$workflowScheduleKey")'`r`n workflow_dispatch:`r`n" + $srcContent = $srcContent.Replace($srcPattern, $replacePattern) + } + $dstFile = Join-Path $dstFolder $fileName if (Test-Path -Path $dstFile -PathType Leaf) { # file exists, compare $dstContent = (Get-Content -Path $dstFile -Encoding UTF8 -Raw).Replace("`r", "").Replace("`n", "`r`n") if ($dstContent -ne $srcContent) { Write-Host "Updated $name ($(Join-Path $dstPath $filename)) available" - $updateFiles += @{ "SrcFile" = "$srcFile"; "DstFile" = Join-Path $dstPath $filename } + $updateFiles += @{ "DstFile" = Join-Path $dstPath $filename; "content" = $srcContent } } } else { # new file Write-Host "New $name ($(Join-Path $dstPath $filename)) available" - $updateFiles += @{ "SrcFile" = "$srcFile"; "DstFile" = Join-Path $dstPath $filename } + $updateFiles += @{ "DstFile" = Join-Path $dstPath $filename; "content" = $srcContent } } } } @@ -198,7 +207,7 @@ try { New-Item -Path $path -ItemType Directory | Out-Null } Write-Host "Update $($_.DstFile)" - Copy-Item -Path $_.SrcFile -Destination $_.DstFile -Force + Set-Content -Path $_.DstFile -Encoding UTF8 -Value $_.Content } $removeFiles | ForEach-Object { Write-Host "Remove $_" diff --git a/Actions/ReadSecrets/ReadSecretsHelper.psm1 b/Actions/ReadSecrets/ReadSecretsHelper.psm1 index 51b24742..6aca502f 100644 --- a/Actions/ReadSecrets/ReadSecretsHelper.psm1 +++ b/Actions/ReadSecrets/ReadSecretsHelper.psm1 @@ -102,7 +102,7 @@ function ConnectAzureKeyVaultIfNeeded { Clear-AzContext -Scope Process Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue Connect-AzAccount -ServicePrincipal -Tenant $tenantId -Credential $credential | Out-Null - Set-AzContext -Subscription $subscriptionId -Tenant $tenantId | Out-Null + Set-AzContext -SubscriptionId $subscriptionId | Out-Null } $script:keyvaultConnectionExists = $true Write-Host "Successfully connected to Azure Key Vault." diff --git a/Actions/RunPipeline/RunPipeline.ps1 b/Actions/RunPipeline/RunPipeline.ps1 index 81383d68..4b3ddddb 100644 --- a/Actions/RunPipeline/RunPipeline.ps1 +++ b/Actions/RunPipeline/RunPipeline.ps1 @@ -122,9 +122,12 @@ try { exit } - $additionalCountries = @() - + $additionalCountries = $repo.additionalCountries + $imageName = "" + if ($repo.gitHubRunner -ne "windows-latest") { + $imageName = $repo.cacheImageName + } $authContext = $null $environmentName = "" $CreateRuntimePackages = $false @@ -189,12 +192,12 @@ try { -enableAppSourceCop:$repo.enableAppSourceCop ` -enablePerTenantExtensionCop:$repo.enablePerTenantExtensionCop ` -enableUICop:$repo.enableUICop ` + -customCodeCops:$repo.customCodeCops ` -azureDevOps:($environment -eq 'AzureDevOps') ` -gitLab:($environment -eq 'GitLab') ` -gitHubActions:($environment -eq 'GitHubActions') ` -failOn 'error' ` -AppSourceCopMandatoryAffixes $repo.appSourceCopMandatoryAffixes ` - -AppSourceCopSupportedCountries @() ` -additionalCountries $additionalCountries ` -buildArtifactFolder $buildArtifactFolder ` -CreateRuntimePackages:$CreateRuntimePackages ` diff --git a/Actions/TelemetryHelper.psm1 b/Actions/TelemetryHelper.psm1 index c2c6dbca..e7498b65 100644 --- a/Actions/TelemetryHelper.psm1 +++ b/Actions/TelemetryHelper.psm1 @@ -1,25 +1,28 @@ $signals = @{ - "DO0070" = "AL-Go action ran: AddExistingApp"; - "DO0071" = "AL-Go action ran: CheckForUpdates"; - "DO0072" = "AL-Go action ran: CreateApp"; - "DO0073" = "AL-Go action ran: CreateDevelopmentEnvironment"; - "DO0074" = "AL-Go action ran: CreateReleaseNotes"; - "DO0075" = "AL-Go action ran: Deploy"; - "DO0076" = "AL-Go action ran: IncrementVersionNumber"; - "DO0077" = "AL-Go action ran: PipelineCleanup"; - "DO0078" = "AL-Go action ran: ReadSecrets"; - "DO0079" = "AL-Go action ran: ReadSettings"; - "DO0080" = "AL-Go action ran: RunPipeline"; + "DO0070" = "AL-Go action ran: AddExistingApp" + "DO0071" = "AL-Go action ran: CheckForUpdates" + "DO0072" = "AL-Go action ran: CreateApp" + "DO0073" = "AL-Go action ran: CreateDevelopmentEnvironment" + "DO0074" = "AL-Go action ran: CreateReleaseNotes" + "DO0075" = "AL-Go action ran: Deploy" + "DO0076" = "AL-Go action ran: IncrementVersionNumber" + "DO0077" = "AL-Go action ran: PipelineCleanup" + "DO0078" = "AL-Go action ran: ReadSecrets" + "DO0079" = "AL-Go action ran: ReadSettings" + "DO0080" = "AL-Go action ran: RunPipeline" - "DO0090" = "AL-Go workflow ran: AddExistingAppOrTestApp"; - "DO0091" = "AL-Go workflow ran: CiCd"; - "DO0092" = "AL-Go workflow ran: CreateApp"; - "DO0093" = "AL-Go workflow ran: CreateOnlineDevelopmentEnvironment"; - "DO0094" = "AL-Go workflow ran: CreateRelease"; - "DO0095" = "AL-Go workflow ran: CreateTestApp"; - "DO0096" = "AL-Go workflow ran: IncrementVersionNumber"; - "DO0097" = "AL-Go workflow ran: PublishToEnvironment"; - "DO0098" = "AL-Go workflow ran: UpdateGitHubGoSystemFiles"; + "DO0090" = "AL-Go workflow ran: AddExistingAppOrTestApp" + "DO0091" = "AL-Go workflow ran: CiCd" + "DO0092" = "AL-Go workflow ran: CreateApp" + "DO0093" = "AL-Go workflow ran: CreateOnlineDevelopmentEnvironment" + "DO0094" = "AL-Go workflow ran: CreateRelease" + "DO0095" = "AL-Go workflow ran: CreateTestApp" + "DO0096" = "AL-Go workflow ran: IncrementVersionNumber" + "DO0097" = "AL-Go workflow ran: PublishToEnvironment" + "DO0098" = "AL-Go workflow ran: UpdateGitHubGoSystemFiles" + "DO0099" = "AL-Go workflow ran: NextMajor" + "DO0100" = "AL-Go workflow ran: NextMinor" + "DO0101" = "AL-Go workflow ran: Current" } function CreateScope { diff --git a/README.md b/README.md index 82546871..174a3332 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,31 @@ # AL-Go for GitHub -What is AL-Go for GitHub? +AL-Go for GitHub is a set of GitHub templates and actions, which can be used to setup and maintain professional DevOps processes for your Business Central AL projects. + +The goal is that people who have created their GitHub repositories based on the AL-Go templates, can maintain these repositories and stay current just by running a workflow, which updates their repositories. This includes necessary changes to scripts and workflows to cope with new features and functions in Business Central. + +The template repositories to use as starting point are: +- https://github.com/microsoft/AL-Go-PTE is the GitHub repository template for Per Tenant Extenstions. For creating a Per Tenant Extensions, this is your starting point. +- https://github.com/microsoft/AL-Go-AppSource is the GitHub repository template for AppSource apps. For creating an AppSource App, this is your starting point. + + +The below usage scenarios takes you through how to get started and how to perform the most common tasks. Usage scenarios: -1. [Create a new per tenant extension (like AL Go) and start developing in VS Code](Scenarios/1.md) -1. [Add a test app to an existing project](Scenarios/2.md) -1. [Register a customer sandbox environment for Continuous Deployment using S2S](Scenarios/3.md) -1. [Create a release of your application](Scenarios/4.md) -1. [Register a customer production environment for Manual Deployment](Scenarios/5.md) -1. [Update AL-Go system files](Scenarios/6.md) -1. [Use Azure KeyVault for secrets with AL-Go](Scenarios/7.md) -1. [Create Online Development Environment from VS Code](Scenarios/8.md) -1. [Create Online Development Environment from GitHub](Scenarios/9.md) -1. [Setup CI/CD for an existing per tenant extension (BingMaps)](Scenarios/10.md) -1. [Setup CI/CD for an existing AppSource App](Scenarios/11.md) -1. [Enable KeyVault access for your AppSource App during development and/or tests](Scenarios/12.md) -1. [Introducing a dependency to another GitHub repository](Scenarios/AppDependencies.md) +1. [Create a new per-tenant extension (like AL Go) and start developing in VS Code](Scenarios/GetStarted.md) +2. [Add a test app to an existing project](Scenarios/AddATestApp.md) +3. [Register a customer sandbox environment for Continuous Deployment using S2S](Scenarios/RegisterSandboxEnvironment.md) +4. [Create a release of your application](Scenarios/CreateRelease.md) +5. [Register a customer production environment for Manual Deployment](Scenarios/RegisterProductionEnvironment.md) +6. [Update AL-Go system files](Scenarios/UpdateAlGoSystemFiles.md) +7. [Use Azure KeyVault for secrets with AL-Go](Scenarios/UseAzureKeyVault.md) +8. [Create Online Development Environment from VS Code](Scenarios/CreateOnlineDevEnv.md) +9. [Create Online Development Environment from GitHub](Scenarios/CreateOnlineDevEnv2.md) +10. [Set up CI/CD for an existing per tenant extension (BingMaps)](Scenarios/SetupCiCdForExistingPTE.md) +11. [Set up CI/CD for an existing AppSource App](Scenarios/SetupCiCdForExistingAppSourceApp.md) +12. [Enable KeyVault access for your AppSource App during development and/or tests](Scenarios/EnableKeyVaultForAppSourceApp.md) +13. [Set up your own GitHub runner to increase build performance](Scenarios/SelfHostedGitHubRunner.md) +14. [Introducing a dependency to another GitHub repository](Scenarios/AppDependencies.md) +15. [Enabling Telemetry for AL-Go workflows and actions](Scenarios/EnableTelemetry.md) **Note:** Please refer to [this description](Scenarios/settings.md) to learn about the settings file and how you can modify default behaviors. # This project @@ -22,8 +33,6 @@ This project in the main source repository for AL-Go for GitHub. This project is - https://github.com/microsoft/AL-Go-PTE is the GitHub repository template for Per Tenant Extenstions. For creating a Per Tenant Extensions, this is your starting point. - https://github.com/microsoft/AL-Go-AppSource is the GitHub repository template for AppSource apps. For creating an AppSource App, this is your starting point. - -and last, but not least a repository with the GitHub actions used by the templates. - https://github.com/microsoft/AL-Go-Actions is the GitHub repository containing the GitHub Actions used by the templates above. # Contributing diff --git a/Scenarios/7.md b/Scenarios/7.md deleted file mode 100644 index 847157ff..00000000 --- a/Scenarios/7.md +++ /dev/null @@ -1,9 +0,0 @@ -# #7 Use Azure KeyVault for secrets with AL-Go -*Prerequisites: A completed [scenario 6](6.md), an Azure KeyVault and you will need to follow the guidelines on how to connect to an Azure KeyVault as specified here: https://docs.microsoft.com/en-us/azure/developer/github/github-key-vault. Add your KeyVault name to the the JSON construct from this walkthrough (using **“keyVaultName” : “{your keyvault name}”**) and add this JSON construct as a repository secret called AZURE_CREDENTIALS. You can also specify the KeyVault name in the AL-Go settings file if you do not wait to mess with the JSON construct.* - -1. Add the **authContext** secret (see scenario 3) and the **ghTokenWorkflow** secret (see scenario 6) as secrets in your KeyVault. Remove the secrets from repository secrets and environment secrets. -1. Run the CI/CD pipeline to see that the deployment still works, reading the **authContext** secret from the KeyVault. -![runpipeline](/images/7a.png) -1. Redo scenario 6 to see that Update AL-Go System files still works. ---- -[back](/README.md) diff --git a/Scenarios/2.md b/Scenarios/AddATestApp.md similarity index 74% rename from Scenarios/2.md rename to Scenarios/AddATestApp.md index 802bf0ab..60905f46 100644 --- a/Scenarios/2.md +++ b/Scenarios/AddATestApp.md @@ -1,21 +1,21 @@ # #2 Add a test app to an existing project -*Prerequisites: A completed [scenario 1](1.md)* +*Prerequisites: A completed [scenario 1](GetStarted.md)* 1. On **github.com**, open **Actions** on your solution, select **Create a new test app** and then choose **Run workflow**. Enter values for **name**, **publisher**, and **ID range** and choose **Run workflow** -![Run Workflow](/images/2a.png) +![Run Workflow](/Scenarios/images/2a.png) 1. When the workflow is done, navigate to **Pull Requests**, **inspect the PR** and **Merge the pull request** -![Pull Request](/images/2b.png) +![Pull Request](/Scenarios/images/2b.png) 1. Under **Actions**, you will see that a Merge pull request CI workflow has been kicked off -![Workflows](/images/2c.png) +![Workflows](/Scenarios/images/2c.png) 1. If you wait for the workflow to complete, you will see that it fails. -![Fail](/images/2d.png) +![Fail](/Scenarios/images/2d.png) 1. Inspecting the build, you can see the details of the error. -![Test failure](/images/2e.png) +![Test failure](/Scenarios/images/2e.png) 1. To fix this, open VS Code, pull changes from the server using the sync button, open the **HelloWorld.Test.al** file and fix the test message. -![Bug fix](/images/2f.png) +![Bug fix](/Scenarios/images/2f.png) 1. Stage, Commit, and Push the change. On github.com, under **Actions** you will see that your check-in caused another CI workflow to be kicked off. -![CI Workflow](/images/2g.png) +![CI Workflow](/Scenarios/images/2g.png) 1. This time it should be passing and if you investigate the CI/CD workflow, you will see that the deploy step has been skipped as no environment existed. -![Success](/images/2h.png) +![Success](/Scenarios/images/2h.png) --- [back](/README.md) diff --git a/Scenarios/AppDependencies.md b/Scenarios/AppDependencies.md index cdbe80d8..76097854 100644 --- a/Scenarios/AppDependencies.md +++ b/Scenarios/AppDependencies.md @@ -1,4 +1,4 @@ -# Introducing a dependency to an app on GitHub +# 14. Introducing a dependency to an app on GitHub If your app has a dependency to another application on a different GitHub repository, the foreign repository can be added to the dependency probing paths (appDependencyProbingPaths) in the AL-Go settings file. The dependency must also be added to the `app.json` file as a dependency. During a build all the apps mentioned in the probing paths will be downloaded and installed on the tenant. diff --git a/Scenarios/8.md b/Scenarios/CreateOnlineDevEnv.md similarity index 78% rename from Scenarios/8.md rename to Scenarios/CreateOnlineDevEnv.md index 0066d511..31c92a86 100644 --- a/Scenarios/8.md +++ b/Scenarios/CreateOnlineDevEnv.md @@ -1,18 +1,18 @@ # #8 Create Online Development Environment from VS Code -*Prerequisites: A completed [scenario 7](7.md)* +*Prerequisites: A completed [scenario 7](UseAzureKeyVault.md)* 1. Open your **App1** project in VS Code, open the **cloudDevEnv.ps1** in your **.AL-Go** folder and run the script. -![Cloud DevEnv](/images/8a.png) +![Cloud DevEnv](/Scenarios/images/8a.png) 1. The script will ask for an **environment name** if it isn’t specified and it will ask whether you want to reuse or **recreate** the environment if it already exists. After this the script will need access to the **admin center API** and will initiate a **device code login** for this purpose. -![Cloud DevEnv](/images/8b.png) +![Cloud DevEnv](/Scenarios/images/8b.png) 1. Open https://aka.ms/devicelogin and paste in the **code provided**, sign in and accept that you are trying to sign in with PowerShell. -![Cloud DevEnv](/images/8c.png) +![Cloud DevEnv](/Scenarios/images/8c.png) 1. Wait for the script to finish. All apps are compiled and published to the online environment using the development scope and **VS Code is ready for RAD development** -![Cloud DevEnv](/images/8d.png) +![Cloud DevEnv](/Scenarios/images/8d.png) 1. Modify your app, press **F5** and select the **Cloud Sandbox** with your new name. -![Cloud DevEnv](/images/8e.png) +![Cloud DevEnv](/Scenarios/images/8e.png) 1. Your online environment will have your app changes. -![Cloud DevEnv](/images/8f.png) +![Cloud DevEnv](/Scenarios/images/8f.png) 1. The `launch.json` file will be updated with your new environment in VS Code. You can decide whether you want to check-in the changes to the repo or only use this locally. --- [back](/README.md) diff --git a/Scenarios/9.md b/Scenarios/CreateOnlineDevEnv2.md similarity index 88% rename from Scenarios/9.md rename to Scenarios/CreateOnlineDevEnv2.md index f5c3d952..3aa56039 100644 --- a/Scenarios/9.md +++ b/Scenarios/CreateOnlineDevEnv2.md @@ -1,5 +1,5 @@ # #9 Create Online Development Environment from GitHub -*Prerequisites: A completed [scenario 7](7.md).* +*Prerequisites: A completed [scenario 7](UseAzureKeyVault.md).* *To create an online development environment, we need to authenticate to our Business Central Admin API using OAuth. The Create Online Dev. Environment workflow works unattended if you provide a secret called **AdminCenterApiCredentials** (either as a GitHub Secret or in a keyvault). At the time when writing this, the Admin Center API does not yet support S2S, meaning that the `AdminCenterApiCredentials` cannot be formatted like explained in section 3, but needs to be formatted as: @@ -11,14 +11,14 @@ At the time when writing this, the Admin Center API does not yet support S2S, me *If you do NOT provide an **AdminCenterApiCredentials** secret, the workflow will initiate a device code flow and you can login using https://aka.ms/devicelogin using this code and have the workflow continue. In order to get the code, you will have to inspect the details of the workflow and open the job called **Check AdminCenterApiCredentials / Initiate Device Login (open to see code)*** -![Run Workflow](/images/9a.png) +![Run Workflow](/Scenarios/images/9a.png) -![Devicecode](/images/9b.png) +![Devicecode](/Scenarios/images/9b.png) 1. On github.com, under **Actions** select the **Create Online Dev. Environment** workflow, choose **Run workflow** and specify the requested **environment name** and whether you want to **reuse the environment** if it already exists and choose **Run workflow**. -![Run Workflow](/images/9c.png) +![Run Workflow](/Scenarios/images/9c.png) 1. When the workflow is complete, inspect the pull request to see the changes in **launch.json**. This environment can now be used from a developer but **note** that two developers cannot share one online environment. -![launch.json](/images/9c.png) +![launch.json](/Scenarios/images/9c.png) 1. Merge the pull request and you are ready to do rapid application development (RAD). --- diff --git a/Scenarios/4.md b/Scenarios/CreateRelease.md similarity index 83% rename from Scenarios/4.md rename to Scenarios/CreateRelease.md index 61188718..dd07d9c5 100644 --- a/Scenarios/4.md +++ b/Scenarios/CreateRelease.md @@ -1,13 +1,13 @@ # #4 Create a release of your application -*Prerequisites: A completed [scenario 3](3.md)* +*Prerequisites: A completed [scenario 3](RegisterSandboxEnvironment.md)* 1. On github.com, open **Actions** in your project and select **Create Release**. Choose **Run workflow**. Enter 1.0 as **name** and **tag** of the release, and then choose **Run workflow**. -![Run workflow](/images/4a.png) +![Run workflow](/Scenarios/images/4a.png) 1. When the **create release** workflow completes, choose the **Code** section to see the releases. -![Run workflow](/images/4b.png) +![Run workflow](/Scenarios/images/4b.png) 1. Choose the release (1.0) and you will see the release. The release notes are pulled from all pull-requests checked in since the last release. The auto-generated release note also contains a list of the new contributers and a link to the full changelog. Choose the **Edit** button (the pencil) to modify the release notes. At the bottom, you can see the artifacts published, both the apps and the source code. A tag is created in the repository for the release number to always keep this. -![Run workflow](/images/4c.png) +![Run workflow](/Scenarios/images/4c.png) 1. Under **Actions**, select the **CI/CD** workflow and choose **Run workflow** to kick off a new CI/CD workflow. After the CI/CD workflow finishes, you can inspect the workflow output to see that the latest release was used as a baseline for the upgrade tests in the pipeline. You will also see that the new build, just created was deployed to the QA environment automatically. -![Run workflow](/images/4d.png) +![Run workflow](/Scenarios/images/4d.png) --- [back](/README.md) diff --git a/Scenarios/12.md b/Scenarios/EnableKeyVaultForAppSourceApp.md similarity index 100% rename from Scenarios/12.md rename to Scenarios/EnableKeyVaultForAppSourceApp.md diff --git a/Scenarios/EnablingTelemetry.md b/Scenarios/EnablingTelemetry.md index a42b8ba5..e4c8ba90 100644 --- a/Scenarios/EnablingTelemetry.md +++ b/Scenarios/EnablingTelemetry.md @@ -1,12 +1,16 @@ -# Enabling telemetry +# 15. Enabling telemetry If you want to enable partner telemetry add your Application Insights connection string to the AL-GO settings file. the settings structure is: -"PartnerTelemetryConnectionString" = "" +``` +"PartnerTelemetryConnectionString": "" +``` You can also decide to send extended telelmetry to Microsoft. This would be helpful to investigate an issue. To enable the extended telemetry add the following property to the AL-GO settings file: -SendExtendedTelemetryToMicrosoft = "true" +``` +"SendExtendedTelemetryToMicrosoft" : true +``` Each workflow starts with initialization task and ends with a postprocess task. During the initialization an operation Id(Guid) is generated and added to all the tasks in the workflow as ParentID. This property can be used to see all the signals sent for a workflow. The postprocess task sends the signal and duration of a workflow. Additionally, each task has its own signal and operationId. This could be used to investigate a task. diff --git a/Scenarios/1.md b/Scenarios/GetStarted.md similarity index 84% rename from Scenarios/1.md rename to Scenarios/GetStarted.md index c4d99300..797d50e4 100644 --- a/Scenarios/1.md +++ b/Scenarios/GetStarted.md @@ -2,31 +2,31 @@ *Prerequisites: A GitHub account, VS-Code (with AL and PowerShell extensions installed), and Docker installed locally* 1. Navigate to https://github.com/microsoft/AL-Go-PTE and choose **Use this template** -![Use this template](/images/1a.png) +![Use this template](/Scenarios/images/1a.png) 1. Enter **app1** as repository name, select Public or Private and select **Create Repository from template** 1. Select **Actions** -> **Create a new app** -> **Run workflow** -![Run workflow](/images/1b.png) +![Run workflow](/Scenarios/images/1b.png) 1. Enter **Name**, **Publisher**, **ID range** and specify **Y** in **Direct COMMIT** and choose **Run workflow**. 1. When the workflow is complete, select **< > Code** in the top bar 1. Choose the **Code** button and copy the **https Clone Url** (in this picture: *https://github.com/freddydk/App1.git*) -![Clone](/images/1c.png) +![Clone](/Scenarios/images/1c.png) 1. Start **VS Code**, press **Ctrl+Alt+P** and select **Git Clone**, paste the clone URL and select a folder in which you want to clone the directory. 1. **Open the cloned repository** and **open the workspace** when VS Code asks you (or do it manually) 1. In the **.AL-Go** folder, choose the **localDevEnv.ps1** script and Run the PowerShell script. -![LocalDevEnv](/images/1d.png) +![LocalDevEnv](/Scenarios/images/1d.png) 1. Answer the questions asked about container name, authentication mechanism, credentials and select none for license file. The script might show a dialog asking for permissions to run docker commands, select **Yes** in this dialog. Wait for completion of the script. -![LocalDevEnv Done](/images/1e.png) +![LocalDevEnv Done](/Scenarios/images/1e.png) 1. In VS Code, press **Ctrl+Alt+P** and **clear the credentials cache**. 1. Open the **HelloWorld.al** file, modify the string and press **F5**. Depending on authentication selected VS Code might ask for the credentials you provided earlier. 1. Login to **Business Central** and your **very own world** opens up! -![Very own world](/images/1f.png) +![Very own world](/Scenarios/images/1f.png) 1. Back in **VS Code**, you will see that in addition to your changes in HelloWorld.al, the launch.json was also modified with the information about the local environment. **Stage your changes**, **commit** and **push** -![Launch.json](/images/1g.png) +![Launch.json](/Scenarios/images/1g.png) 1. Back on github.com, investigate your **Workflows**. -![Workflows](/images/1h.png) +![Workflows](/Scenarios/images/1h.png) 1. When the build is done, inspect the **Build summary** (no test app) -![Build Summary](/images/1i.png) +![Build Summary](/Scenarios/images/1i.png) 1. Inspect the workflow run by choosing the **build job**, expanding the **Run Pipeline** section and the **Compiling apps** subsection -![Inspect](/images/1j.png) +![Inspect](/Scenarios/images/1j.png) --- [back](/README.md) diff --git a/Scenarios/5.md b/Scenarios/RegisterProductionEnvironment.md similarity index 66% rename from Scenarios/5.md rename to Scenarios/RegisterProductionEnvironment.md index 715cb984..f90a631d 100644 --- a/Scenarios/5.md +++ b/Scenarios/RegisterProductionEnvironment.md @@ -1,8 +1,8 @@ # #5 Register a customer production environment for Manual Deployment -*Prerequisites: A completed [scenario 4](4.md), an online production environment setup for S2S as specified in task 2 here [Using Service to Service Authentication - Business Central | Microsoft Docs](https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/automation-apis-using-s2s-authentication), using the same AAD App as scenario 3* +*Prerequisites: A completed [scenario 4](CreateRelease.md), an online production environment setup for S2S as specified in task 2 here [Using Service to Service Authentication - Business Central | Microsoft Docs](https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/automation-apis-using-s2s-authentication), using the same AAD App as scenario 3* 1. Following the process in step 3, you can add an environment to the GitHub repository under settings called **MYPROD (Production)** (the name of your production environment followed by “ (Production)”), which maps to a production environment called **MYPROD**. Remember the **AUTHCONTEXT** Secret. Apps will NOT be deployed to production environments from the CI/CD pipeline, by adding the **(Production)** tag, the environment will be filtered out already during the **Analyze** phase. You need to run the **Publish To Environment** workflow to publish the apps. Leave the App version as **current**, which means that the **latest released bits** are published to **MYPROD**. -![Run workflow](/images/5a.png) +![Run workflow](/Scenarios/images/5a.png) 1. After running the **Publish to Environment** workflow, you should see that the app was deployed to the **MYPROD** environment only. -![Run workflow](/images/5b.png) +![Run workflow](/Scenarios/images/5b.png) --- [back](/README.md) diff --git a/Scenarios/3.md b/Scenarios/RegisterSandboxEnvironment.md similarity index 61% rename from Scenarios/3.md rename to Scenarios/RegisterSandboxEnvironment.md index 82ec02a3..9002f33d 100644 --- a/Scenarios/3.md +++ b/Scenarios/RegisterSandboxEnvironment.md @@ -1,15 +1,15 @@ # #3 Register a customer sandbox environment for Continuous Deployment using S2S -*Prerequisites: A completed [scenario 2](2.md), an AAD App, and an online sandbox environment called QA with the setup for S2S as specified in task 1 and 2 here [Using Service to Service Authentication - Business Central | Microsoft Docs](https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/automation-apis-using-s2s-authentication) completed. You will also need the `BcContainerHelper PowerShell` module installed on your computer.* +*Prerequisites: A completed [scenario 2](AddATestApp.md), an AAD App, and an online sandbox environment called QA with the setup for S2S as specified in task 1 and 2 here [Using Service to Service Authentication - Business Central | Microsoft Docs](https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/automation-apis-using-s2s-authentication) completed. You will also need the `BcContainerHelper PowerShell` module installed on your computer.* 1. On github.com, open **Settings** and **Environments** in your project. Click **New Environment** and specify the **name of the environment** you have created in your tenant. -![Add Environment](/images/3a.png) +![Add Environment](/Scenarios/images/3a.png) 1. Under **Environment secrets**, choose the **Add Secret** action. Create a secret called **AUTHCONTEXT**, and enter a **COMPRESSED JSON** construct with 3 values: TenantID (where the environment lives), ClientID, and ClientSecret (from the pre-requisites), like: `{"TenantID":"","ClientID":"","ClientSecret":""}` -![Add Environment](/images/3b.png) +![Add Environment](/Scenarios/images/3b.png) 1. Navigate to **Actions**, select the **Publish To Environment** workflow and choose **Run workflow**. Enter **latest** in the **App version** field and the **name of your environment** or keep the * in the **environment to receive the new version** field. Click **Run workflow**. -![Add Environment](/images/3c.png) +![Add Environment](/Scenarios/images/3c.png) 1. When the workflow completes, you can inspect the output of the workflow. -![Add Environment](/images/3d.png) +![Add Environment](/Scenarios/images/3d.png) 1. And/or you can open the QA environment, navigate to Customers and see that your very own Hello World message appears. -![Add Environment](/images/3e.png) +![Add Environment](/Scenarios/images/3e.png) --- [back](/README.md) diff --git a/Scenarios/SelfHostedGitHubRunner.md b/Scenarios/SelfHostedGitHubRunner.md new file mode 100644 index 00000000..acae72d8 --- /dev/null +++ b/Scenarios/SelfHostedGitHubRunner.md @@ -0,0 +1,39 @@ +# #13 Set up your own GitHub runner to increase build performance +*Prerequisites: An AL-Go repository setup using one of the scenarios* + +When running the CI/CD workflow, the build job is by far the most time-consuming job. By adding your own GitHub Runner, which can cache the generic image, the build image and also the artifacts, the time for running the build job can become much faster. + +GitHub runners can be registered for an organization (accessible for all repositories in the organization) or for a single repository. + +1. Navigate to https://github.com/organizations/{organization}/settings/actions/runners/new to create a self-hosted runner for your organization. Use https://github.com/{organization}/{repository}/settings/actions/runners to create a self-hosted runner for a single repository. +![Organization new runner](/Scenarios/images/13a.png) +1. To create a self-hosted runner manually, choose Windows under Runner Image and x64 in architecture and follow the description on how to create a self-hosted runner manually, then go to step 9 to continue the configuration. +1. To create an Azure VM hosting x self-hosted runners, open a new tab and navigate to https://aka.ms/getbuildagent. +1. Enter the **Resource Group name**, **Region**, **VM Name**, **Admin Password** of your choice. +1. Enter the **number of agents** you want to create on the VM. +1. Grab the **token**, the **organization Url**, and the **Agent Url** from the Create Self-Hosted runner page, and specify **self-hosted** in labels. +![getbuildagent](/Scenarios/images/13b.png) +1. Select **Review and Create** and then review the deployment and choose **Create**. +1. Wait for the Azure VM creation to finalize, navigate back to see that the Runners have been registered and are ready to use. +![Runners](/Scenarios/images/13c.png) +1. On the list of Runners on GitHub, choose the runner group **Default** and allow public repositories if your repository is public. +![public](/Scenarios/images/13f.png) +1. Now navigate to your project settings file (.AL-Go/settings.json) and set **gitHubRunner** to **self-hosted**. +1. Save and inspect your workflows performance increase on the second run. +1. Inspect that one of the runners pick up the workflow. +![Active](/Scenarios/images/13d.png) +1. Clicking the runner reveals that the job it is running. +![Job](/Scenarios/images/13e.png) + +## Additional info on build performance + +1. Running 6 CI/CD workflows simultanously, causes 1 workflow to wait as I only had 5 runners. +![Wait](/Scenarios/images/13g.png) +1. Connecting to the runner VM and looking at utilization indicates that the VM is pretty busy and probably over-allocated when starting 5+ builds at the same time. Every build was ~50% slower than when running only 1 build. +![CPU](/Scenarios/images/13h.png) +1. Decreasing the number of runners to 4 causes the build performance to be similar to when running just 1 build. +1. Turning off real-time protection on the self-hosted runner makes builds go ~25% faster. +![Better utilization](/Scenarios/images/13i.png) + +--- +[back](/README.md) diff --git a/Scenarios/11.md b/Scenarios/SetupCiCdForExistingAppSourceApp.md similarity index 87% rename from Scenarios/11.md rename to Scenarios/SetupCiCdForExistingAppSourceApp.md index e34348cf..ea924d73 100644 --- a/Scenarios/11.md +++ b/Scenarios/SetupCiCdForExistingAppSourceApp.md @@ -1,22 +1,22 @@ # #11 Set up CI/CD for an existing AppSource App *Prerequisites: A GitHub account and experience from the other scenarios* 1. Navigate to https://github.com/microsoft/AL-Go-AppSource and choose **Use this template**. -![Use this template](/images/11a.png) +![Use this template](/Scenarios/images/11a.png) 1. Enter **app3** as repository name and select **Create Repository from template**. 1. My current AppSource App is using **Azure DevOps**, I download the **entire source** as a **.zip** file and place it on **Dropbox** or **Azure Blob storage** and create a **secure download Url** to the .zip file. -![Create Zip Url](/images/11b.png) +![Create Zip Url](/Scenarios/images/11b.png) 1. Back on github.com, under **Actions**, select the **Add existing app or test app** workflow and choose **Run workflow**. Paste in the **Secure Download URL** and choose **Run Workflow**. When the workflow finishes, complete the pull request created. 1. A CI workflow is kicked off by the pull request, this will fail with this error: *For AppSource Apps with AppSourceCop enabled, you need to specify AppSourceCopMandatoryAffixes in .AL-Go\settings.json.* 1. If you fix this and re-run, you will get another error: *When building an AppSource App, you need to create a secret called LicenseFileUrl, containing a secure URL to your license file with permission to the objects used in the app*. -1. I will use my **KeyVault from [Scenario 7](7.md)**, by adding a secret called **AZURE_CREDENTIALS** to my GitHub repo. And then add or modify the following 3 properties in the **.AL-Go\settings.json** file: +1. I will use my **KeyVault from [Scenario 7](UseAzureKeyVault.md)**, by adding a secret called **AZURE_CREDENTIALS** to my GitHub repo. And then add or modify the following 3 properties in the **.AL-Go\settings.json** file: ```json "LicenseFileUrlSecretName": "LicenseFile", "AppSourceCopMandatoryAffixes": [ "BingMaps" ], ``` 1. Meaning that the **AppSourceCopMandatoryAffixes** is set to check that I use **BingMaps** as an affix for my objects. The second setting **is only needed** if my secret is called something else than expected. AL-Go is by default looking for a secret called **LicenseFileUrl**, but you might have multiple repositories sharing the same KeyVault but needing different secrets. In this case you create a setting called **"\SecretName"**, specifying the actual secret name in the KeyVault. This mechanism is used for all secrets. In my **BuildVariables KeyVault**, the **LicenseFileUrl** secret is called **LicenseFile**. After these changes, my CI pipeline completes: -![Pipeline](/images/11c.png) +![Pipeline](/Scenarios/images/11c.png) 1. AppSource apps need to be code-signed. To achieve this, you must create two secrets in the GitHub repo or in your KeyVault. **CodeSignCertificateUrl** should be a secure download URL to your `.pfx` file and **CodeSignCertificatePassword** should be the password for this .pfx file. Adding these secrets will cause the **CI** workflow and the **Create Release** workflow to sign the .app files. In the pipeline, you will see a new step. -![Signing App](/images/11d.png) +![Signing App](/Scenarios/images/11d.png) If your secrets are called something else than **CodesignCertificateUrl** and **CodesignCertificatePassword**, you can add an indirection to the **.AL-Go\settings.json** file: ```json "CodeSignCertificateUrlSecretName": "myCodeSignCertUrl", diff --git a/Scenarios/10.md b/Scenarios/SetupCiCdForExistingPTE.md similarity index 78% rename from Scenarios/10.md rename to Scenarios/SetupCiCdForExistingPTE.md index 5d7c3012..f37cb14c 100644 --- a/Scenarios/10.md +++ b/Scenarios/SetupCiCdForExistingPTE.md @@ -4,16 +4,16 @@ We will use the BingMaps sample app, which is on Azure DevOps here: https://dev. Copy following URL (a direct download of the main branch of the BingMaps sample) to the clipboard: https://dev.azure.com/businesscentralapps/BingMaps/_apis/git/repositories/BingMaps/items/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=0&versionDescriptor[version]=master&resolveLfs=true&$format=zip&api-version=5.0&download=true – you can download the .zip file and see the content of it.* 1. Navigate to https://github.com/microsoft/AL-Go-PTE and then choose **Use this template**. -![Use this template](/images/10a.png) +![Use this template](/Scenarios/images/10a.png) 1. Enter **app2** as repository name and select **Create Repository from template**. 1. Under **Actions** select the **Add existing app or test app** workflow and choose **Run workflow**. 1. In the **Direct Download URL** field, paste in the direct download URL of the BingMaps sample from above. 1. When the workflow is complete, inspect the **Pull request**. -![Pull Request](/images/10b.png) +![Pull Request](/Scenarios/images/10b.png) 1. Merge the pull request. The **CI/CD** workflow will kick off. -![CI/CD](/images/10c.png) +![CI/CD](/Scenarios/images/10c.png) 1. After the workflow completes, you can investigate the output and see that everything works. -![Success](/images/10d.png) -1. Use [scenario 3](3.md), [scenario 4](4.md), and [scenario 5](5.md) to set up customer environments, publish and test the app. +![Success](/Scenarios/images/10d.png) +1. Use [scenario 3](RegisterSandboxEnvironment.md), [scenario 4](CreateRelease.md), and [scenario 5](RegisterProductionEnvironment.md) to set up customer environments, publish and test the app. --- [back](/README.md) diff --git a/Scenarios/6.md b/Scenarios/UpdateAlGoSystemFiles.md similarity index 86% rename from Scenarios/6.md rename to Scenarios/UpdateAlGoSystemFiles.md index e6069ba4..c87e833d 100644 --- a/Scenarios/6.md +++ b/Scenarios/UpdateAlGoSystemFiles.md @@ -1,22 +1,22 @@ # #6 Update AL-Go system files -*Prerequisites: A completed [scenario 5](5.md)* +*Prerequisites: A completed [scenario 5](RegisterProductionEnvironment.md)* 1. Every time a CI/CD pipeline runs, it checks whether there are updates to AL-Go system files. AL-Go System files are scripts in the **.AL-Go folder** and workflows in the **.github folder**. Looking into the details of the Check for updates to Al-Go system files, usually looks like this -![CI/CD](/images/6a.png) +![CI/CD](/Scenarios/images/6a.png) 1. In VS Code, try to modify the **LocalDevEnv.ps1** file, **stage** the change, **commit** and **push**. -![localdevenv](/images/6b.png) +![localdevenv](/Scenarios/images/6b.png) 1. Now there is a difference. AL-Go doesn’t support that anybody changes the AL-Go system files and will warn about these changes. The CI/CD pipeline, which kicked off when pushing the change, tells me about this. -![summary](/images/6c.png) +![summary](/Scenarios/images/6c.png) 1. To update the AL-Go system files using the Update AL-Go System Files workflow, you need to provide a secret called GHWORKFLOWTOKEN containing a Personal Access Token with permissions to modify workflows 1. In a browser, navigate to [New personal access token](https://github.com/settings/tokens/new) and create a new **personal access token**. Name it, set the expiration date and check the **workflow option** in the list of **scopes**. -![newPAT](/images/6d.png) +![newPAT](/Scenarios/images/6d.png) 1. Generate the token and **copy it to the clipboard**. You won’t be able to see the token again. 1. On github.com, open **Settings** in your project and select **Secrets**. Choose the New repository secret button and create a secret called GHTOKENWORKFLOW and paste the personal access token in the value field and choose **Add secret**. -![PAT](/images/6e.png) +![PAT](/Scenarios/images/6e.png) 1. On github.com, under **Actions** in your project, select the **Update AL-Go system files** workflow and choose **Run workflow**. Leave the **Template Repository URL** blank and choose **Run workflow**. -![update](/images/6e.png) +![update](/Scenarios/images/6e.png) 1. Inspect the pull request and see that it indeed reverts your change to the `LocalDevEnv.ps1` file. -![update](/images/6e.png) +![update](/Scenarios/images/6e.png) 1. By default, this workflow will apply any updates to the **workflow files (in .github\workflows)** or **system scripts (in .AL-Go)** from the template repository used to spin up the repository. If you want to change branch or template Url, you can specify the `templateUrl@branch` when you run the workflow. --- [back](/README.md) diff --git a/Scenarios/UseAzureKeyVault.md b/Scenarios/UseAzureKeyVault.md new file mode 100644 index 00000000..3143a7ca --- /dev/null +++ b/Scenarios/UseAzureKeyVault.md @@ -0,0 +1,9 @@ +# #7 Use Azure KeyVault for secrets with AL-Go +*Prerequisites: A completed [scenario 6](UpdateAlGoSystemFiles.md), an Azure KeyVault and you will need to follow the guidelines on how to connect to an Azure KeyVault as specified here: https://docs.microsoft.com/en-us/azure/developer/github/github-key-vault. Add your KeyVault name to the the JSON construct from this walkthrough (using **“keyVaultName” : “{your keyvault name}”**) and add this JSON construct as a repository secret called AZURE_CREDENTIALS. You can also specify the KeyVault name in the AL-Go settings file if you do not wait to mess with the JSON construct.* + +1. Add the **authContext** secret (see scenario 3) and the **ghTokenWorkflow** secret (see scenario 6) as secrets in your KeyVault. Remove the secrets from repository secrets and environment secrets. +1. Run the CI/CD pipeline to see that the deployment still works, reading the **authContext** secret from the KeyVault. +![runpipeline](/Scenarios/images/7a.png) +1. Redo scenario 6 to see that Update AL-Go System files still works. +--- +[back](/README.md) diff --git a/images/10a.png b/Scenarios/images/10a.png similarity index 100% rename from images/10a.png rename to Scenarios/images/10a.png diff --git a/images/10b.png b/Scenarios/images/10b.png similarity index 100% rename from images/10b.png rename to Scenarios/images/10b.png diff --git a/images/10c.png b/Scenarios/images/10c.png similarity index 100% rename from images/10c.png rename to Scenarios/images/10c.png diff --git a/images/10d.png b/Scenarios/images/10d.png similarity index 100% rename from images/10d.png rename to Scenarios/images/10d.png diff --git a/images/11a.png b/Scenarios/images/11a.png similarity index 100% rename from images/11a.png rename to Scenarios/images/11a.png diff --git a/images/11b.png b/Scenarios/images/11b.png similarity index 100% rename from images/11b.png rename to Scenarios/images/11b.png diff --git a/images/11c.png b/Scenarios/images/11c.png similarity index 100% rename from images/11c.png rename to Scenarios/images/11c.png diff --git a/images/11d.png b/Scenarios/images/11d.png similarity index 100% rename from images/11d.png rename to Scenarios/images/11d.png diff --git a/Scenarios/images/13a.png b/Scenarios/images/13a.png new file mode 100644 index 00000000..2cf19532 Binary files /dev/null and b/Scenarios/images/13a.png differ diff --git a/Scenarios/images/13b.png b/Scenarios/images/13b.png new file mode 100644 index 00000000..7e4a2f96 Binary files /dev/null and b/Scenarios/images/13b.png differ diff --git a/Scenarios/images/13c.png b/Scenarios/images/13c.png new file mode 100644 index 00000000..ff1833a4 Binary files /dev/null and b/Scenarios/images/13c.png differ diff --git a/Scenarios/images/13d.png b/Scenarios/images/13d.png new file mode 100644 index 00000000..f021c14f Binary files /dev/null and b/Scenarios/images/13d.png differ diff --git a/Scenarios/images/13e.png b/Scenarios/images/13e.png new file mode 100644 index 00000000..797938b1 Binary files /dev/null and b/Scenarios/images/13e.png differ diff --git a/Scenarios/images/13f.png b/Scenarios/images/13f.png new file mode 100644 index 00000000..8773b34c Binary files /dev/null and b/Scenarios/images/13f.png differ diff --git a/Scenarios/images/13g.png b/Scenarios/images/13g.png new file mode 100644 index 00000000..6d04c989 Binary files /dev/null and b/Scenarios/images/13g.png differ diff --git a/Scenarios/images/13h.png b/Scenarios/images/13h.png new file mode 100644 index 00000000..77773b5d Binary files /dev/null and b/Scenarios/images/13h.png differ diff --git a/Scenarios/images/13i.png b/Scenarios/images/13i.png new file mode 100644 index 00000000..2d681937 Binary files /dev/null and b/Scenarios/images/13i.png differ diff --git a/images/1a.png b/Scenarios/images/1a.png similarity index 100% rename from images/1a.png rename to Scenarios/images/1a.png diff --git a/images/1b.png b/Scenarios/images/1b.png similarity index 100% rename from images/1b.png rename to Scenarios/images/1b.png diff --git a/images/1c.png b/Scenarios/images/1c.png similarity index 100% rename from images/1c.png rename to Scenarios/images/1c.png diff --git a/images/1d.png b/Scenarios/images/1d.png similarity index 100% rename from images/1d.png rename to Scenarios/images/1d.png diff --git a/images/1e.png b/Scenarios/images/1e.png similarity index 100% rename from images/1e.png rename to Scenarios/images/1e.png diff --git a/images/1f.png b/Scenarios/images/1f.png similarity index 100% rename from images/1f.png rename to Scenarios/images/1f.png diff --git a/images/1g.png b/Scenarios/images/1g.png similarity index 100% rename from images/1g.png rename to Scenarios/images/1g.png diff --git a/images/1h.png b/Scenarios/images/1h.png similarity index 100% rename from images/1h.png rename to Scenarios/images/1h.png diff --git a/images/1i.png b/Scenarios/images/1i.png similarity index 100% rename from images/1i.png rename to Scenarios/images/1i.png diff --git a/images/1j.png b/Scenarios/images/1j.png similarity index 100% rename from images/1j.png rename to Scenarios/images/1j.png diff --git a/images/2a.png b/Scenarios/images/2a.png similarity index 100% rename from images/2a.png rename to Scenarios/images/2a.png diff --git a/images/2b.png b/Scenarios/images/2b.png similarity index 100% rename from images/2b.png rename to Scenarios/images/2b.png diff --git a/images/2c.png b/Scenarios/images/2c.png similarity index 100% rename from images/2c.png rename to Scenarios/images/2c.png diff --git a/images/2d.png b/Scenarios/images/2d.png similarity index 100% rename from images/2d.png rename to Scenarios/images/2d.png diff --git a/images/2e.png b/Scenarios/images/2e.png similarity index 100% rename from images/2e.png rename to Scenarios/images/2e.png diff --git a/images/2f.png b/Scenarios/images/2f.png similarity index 100% rename from images/2f.png rename to Scenarios/images/2f.png diff --git a/images/2g.png b/Scenarios/images/2g.png similarity index 100% rename from images/2g.png rename to Scenarios/images/2g.png diff --git a/images/2h.png b/Scenarios/images/2h.png similarity index 100% rename from images/2h.png rename to Scenarios/images/2h.png diff --git a/images/3a.png b/Scenarios/images/3a.png similarity index 100% rename from images/3a.png rename to Scenarios/images/3a.png diff --git a/images/3b.png b/Scenarios/images/3b.png similarity index 100% rename from images/3b.png rename to Scenarios/images/3b.png diff --git a/images/3c.png b/Scenarios/images/3c.png similarity index 100% rename from images/3c.png rename to Scenarios/images/3c.png diff --git a/images/3d.png b/Scenarios/images/3d.png similarity index 100% rename from images/3d.png rename to Scenarios/images/3d.png diff --git a/images/3e.png b/Scenarios/images/3e.png similarity index 100% rename from images/3e.png rename to Scenarios/images/3e.png diff --git a/images/4a.png b/Scenarios/images/4a.png similarity index 100% rename from images/4a.png rename to Scenarios/images/4a.png diff --git a/images/4b.png b/Scenarios/images/4b.png similarity index 100% rename from images/4b.png rename to Scenarios/images/4b.png diff --git a/images/4c.png b/Scenarios/images/4c.png similarity index 100% rename from images/4c.png rename to Scenarios/images/4c.png diff --git a/images/4d.png b/Scenarios/images/4d.png similarity index 100% rename from images/4d.png rename to Scenarios/images/4d.png diff --git a/images/5a.png b/Scenarios/images/5a.png similarity index 100% rename from images/5a.png rename to Scenarios/images/5a.png diff --git a/images/5b.png b/Scenarios/images/5b.png similarity index 100% rename from images/5b.png rename to Scenarios/images/5b.png diff --git a/images/6a.png b/Scenarios/images/6a.png similarity index 100% rename from images/6a.png rename to Scenarios/images/6a.png diff --git a/images/6b.png b/Scenarios/images/6b.png similarity index 100% rename from images/6b.png rename to Scenarios/images/6b.png diff --git a/images/6c.png b/Scenarios/images/6c.png similarity index 100% rename from images/6c.png rename to Scenarios/images/6c.png diff --git a/images/6d.png b/Scenarios/images/6d.png similarity index 100% rename from images/6d.png rename to Scenarios/images/6d.png diff --git a/images/6e.png b/Scenarios/images/6e.png similarity index 100% rename from images/6e.png rename to Scenarios/images/6e.png diff --git a/images/6f.png b/Scenarios/images/6f.png similarity index 100% rename from images/6f.png rename to Scenarios/images/6f.png diff --git a/images/6g.png b/Scenarios/images/6g.png similarity index 100% rename from images/6g.png rename to Scenarios/images/6g.png diff --git a/images/7a.png b/Scenarios/images/7a.png similarity index 100% rename from images/7a.png rename to Scenarios/images/7a.png diff --git a/images/8a.png b/Scenarios/images/8a.png similarity index 100% rename from images/8a.png rename to Scenarios/images/8a.png diff --git a/images/8b.png b/Scenarios/images/8b.png similarity index 100% rename from images/8b.png rename to Scenarios/images/8b.png diff --git a/images/8c.png b/Scenarios/images/8c.png similarity index 100% rename from images/8c.png rename to Scenarios/images/8c.png diff --git a/images/8d.png b/Scenarios/images/8d.png similarity index 100% rename from images/8d.png rename to Scenarios/images/8d.png diff --git a/images/8e.png b/Scenarios/images/8e.png similarity index 100% rename from images/8e.png rename to Scenarios/images/8e.png diff --git a/images/8f.png b/Scenarios/images/8f.png similarity index 100% rename from images/8f.png rename to Scenarios/images/8f.png diff --git a/images/9a.png b/Scenarios/images/9a.png similarity index 100% rename from images/9a.png rename to Scenarios/images/9a.png diff --git a/images/9b.png b/Scenarios/images/9b.png similarity index 100% rename from images/9b.png rename to Scenarios/images/9b.png diff --git a/images/9c.png b/Scenarios/images/9c.png similarity index 100% rename from images/9c.png rename to Scenarios/images/9c.png diff --git a/images/9d.png b/Scenarios/images/9d.png similarity index 100% rename from images/9d.png rename to Scenarios/images/9d.png diff --git a/Scenarios/settings.md b/Scenarios/settings.md index 0b681002..16b941aa 100644 --- a/Scenarios/settings.md +++ b/Scenarios/settings.md @@ -8,11 +8,11 @@ When running a workflow or a local script, the settings are applied by reading o **.github\\AL-Go-settings.json** is the repository settings file. This settings file contains settings that are relevant for all projects in the repository. If a settings in the repository settings file is found in a subsequent settings file, it will be overridden by the new value. -**Special note:** The repository settings file can also contains `BcContainerHelper` settings, which will be applied when loading `BcContainerHelper` in a workflow. +**Special note:** The repository settings file can also contains `BcContainerHelper` settings, which will be applied when loading `BcContainerHelper` in a workflow (see expert section). **.AL-Go\\settings.json** is the project settings file. If the repository is a single project, the .AL-Go folder is in the root folder of the repository. If the repository contains multiple projects, there will be a .AL-Go folder in each project folder. -**.AL-Go\\\.settings.json** is the workflow-specific settings file. This option is rarely used, but if you have special settings, which should only be used for one specific workflow, these settings can be added to a settings file with the name of the workflow followed by `.settings.json`. +**.AL-Go\\\.settings.json** is the workflow-specific settings file. This option is used for the Current, NextMinor and NextMajor workflows to determine artifacts and build numbers when running these workflows. **.AL-Go\\\.settings.json** is the user-specific settings file. This option is rarely used, but if you have special settings, which should only be used for one specific user (potentially in the local scripts), these settings can be added to a settings file with the name of the user followed by `.settings.json`. @@ -26,9 +26,19 @@ When running a workflow or a local script, the settings are applied by reading o | appFolders | appFolders should be an array of folders (relative to project root), which contains apps for this project. Apps in these folders are sorted based on dependencies and built and published in that order. | [ ] | | testFolders | testFolders should be an array of folders (relative to project root), which contains test apps for this project. Apps in these folders are sorted based on dependencies and built, published and tests are run in that order. | [ ] | | appSourceCopMandatoryAffixes | This setting is only used if the type is AppSource App. The value is an array of affixes, which is used for running AppSource Cop. | [ ] | -| templateUrl | Defines the URL of the template repository used to create this project and is used for checking and downloading updates to AL-Go System files. || | appDependencyProbingPaths | Array of dependency specifications, from which apps will be downloaded when the CI/CD workflow is starting. Every dependency specification consists of the following properties:
**repo** = repository
**version** = version
**release_status** = release/prerelease/draft
**projects** = projects
**authtoken** = Auth token
**TODO:** complete documentation and add to tests | [ ] | +## Basic Repository settings +The repository settings are only read from the repository settings file (.github\AL-Go-Settings.json) + +| Name | Description | +| :-- | :-- | +| templateUrl | Defines the URL of the template repository used to create this project and is used for checking and downloading updates to AL-Go System files. | +| nextMajorSchedule | CRON schedule for when NextMajor workflow should run. Default is no scheduled run, only manual trigger. Build your CRON string here: https://crontab.guru | +| nextMinorSchedule | CRON schedule for when NextMinor workflow should run. Default is no scheduled run, only manual trigger. Build your CRON string here: https://crontab.guru | +| currentSchedule | CRON schedule for when Current workflow should run. Default is no scheduled run, only manual trigger. Build your CRON string here: https://crontab.guru | +| githubRunner | Specifies which github runner will be used for the pipeline, which is the most time consuming task. Currently, you cannot change which runner is used for all the house-keeping tasks. These will always be run on the default github hosted runner: windows-latest. Read [this](SelfHostedGitHubRunner.md) for more information. + ## Advanced settings | Name | Description | Default value | @@ -36,24 +46,19 @@ When running a workflow or a local script, the settings are applied by reading o | artifact | Determines the artifacts used for building and testing the app.
This setting can either be an absolute pointer to Business Central artifacts (https://... - rarely used) or it can be a search specification for artifacts (\/\/\/\/\/\).
If not specified, the artifacts used will be the latest sandbox artifacts from the country specified in the country setting. | | | companyName | Company name selected in the database, used for running the CI/CD workflow. Default is to use the default company in the selected Business Central localization. | | | versioningStrategy | The versioning strategy determines how versioning is performed in this project. The version number of an app consists of 4 tuples: **Major**.**Minor**.**Build**.**Revision**. **Major** and **Minor** are read from the app.json file for each app. **Build** and **Revision** are calculated. Currently 3 versioning strategies are supported:
**0** = **Build** is the **github [run_number](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context)** for the CI/CD workflow, increased by the **runNumberOffset** setting value (if specified). **Revision** is the **github [run_attempt](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context)** subtracted 1.
**1** = **Build** is the **github [run_id](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context)** for the repository. **Revision** is the **github [run_attempt](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context)** subtracted 1.
**2** = **Build** is the current date as **yyyyMMdd**. **Revision** is the current time as **hhmmss**. Date and time are always **UTC** timezone to avoid problems during daylight savings time change. Note that if two CI/CD workflows are started within the same second, this could yield to identical version numbers from two differentruns.
**+16** use **repoVersion** setting as **appVersion** (**Major** and **Minor**) for all apps | 0 | -| supportedCountries | **TODO:** document | [ ] | -| keyVaultName | **TODO:** document | | -| licenseFileUrlSecretName | **TODO:** document | LicenseFileUrl | -| insiderSasTokenSecretName | **TODO:** document | InsiderSasToken | -| ghTokenWorkflowSecretName | **TODO:** document | GhTokenWorkflow | -| adminCenterApiCredentialsSecretName | **TODO:** document | AdminCenterApiCredentials | -| appDependencies | **TODO:** document | [ ] | -| testDependencies | **TODO:** document | [ ] | -| installApps | **TODO:** document | [ ] | -| installTestApps | **TODO:** document | [ ] | -| enableCodeCop | **TODO:** document | false | -| enableUICop | **TODO:** document | false | -| keyVaultCertificateUrlSecretName | **TODO:** document | | -| keyVaultCertificatePasswordSecretName | **TODO:** document | | -| keyVaultClientIdSecretName | **TODO:** document | | -| codeSignCertificateUrlSecretName | **TODO:** document | CodeSignCertificateUrl | -| codeSignCertificatePasswordSecretName | **TODO:** document | CodeSignCertificatePassword | -| githubRunner | Specifies which github runner will be used for the pipeline, which is the most time consuming task. Currently, you cannot change which runner is used for all the house-keeping tasks. These will always be run on the github hosted runner: windows-latest | windows-latest | +| additionalCountries | This property can be set to an additional number of countries to compile, publish and test your app against during workflows. Note that this setting can be different in NextMajor and NextMinor workflows compared to the CI/CD workflow, by specifying a different value in a workflow settings file. | [ ] | +| keyVaultName | When using Azure KeyVault for the secrets used in your workflows, the KeyVault name needs to be specified in this setting if it isn't specified in the AZURE_CREDENTIALS secret. Read [this](UseAzureKeyVault.md) for more information. | | +| licenseFileUrlSecretName | Specify the name (**NOT the secret itself**) of the LicenseFileUrl secret. Default is LicenseFileUrl. AL-Go for GitHub will look for a secret with this name in GitHub Secrets or Azure KeyVault to use as LicenseFileUrl when running the CI/CD workflow for AppSource Apps. Read [this](SetupCiCdForExistingAppSourceApp.md) for more information. | LicenseFileUrl | +| insiderSasTokenSecretName | Specifies the name (**NOT the secret itself**) of the InsiderSasToken secret. Default is InsiderSasToken. AL-Go for GitHub will look for a secret with this name in GitHub Secrets or Azure KeyVault to use as InsiderSasToken for getting access to Next Minor and Next Major builds. | InsiderSasToken | +| ghTokenWorkflowSecretName | Specifies the name (**NOT the secret itself**) of the GhTokenWorkflow secret. Default is GhTokenWorkflow. AL-Go for GitHub will look for a secret with this name in GitHub Secrets or Azure KeyVault to use as Personal Access Token with permission to mofify workflows when running the Update AL-Go System Files workflow. Read [this](UpdateAlGoSystemFiles.md) for more information. | GhTokenWorkflow | +| adminCenterApiCredentialsSecretName | Specifies the name (**NOT the secret itself**) of the adminCenterApiCredentias secret. Default is adminCenterApiCredentials. AL-Go for GitHub will look for a secret with this name in GitHub Secrets or Azure KeyVault to use when connecting to the Admin Center API when creating Online Development Environments. Read [this](CreateOnlineDevEnv2.md) for more information. | AdminCenterApiCredentials | +| installApps | An array of 3rd party dependency apps, which you do not have access to through the appDependencyProbingPaths. The setting should be an array of secure URLs, where the CI/CD workflow can download the apps. The apps in installApps are downloaded and installed before compiling and installing the apps. | [ ] | +| installTestApps | An array of 3rd party dependency apps, which you do not have access to through the appDependencyProbingPaths. The setting should be an array of secure URLs, where the CI/CD workflow can download the apps. The apps in installTestApps are downloaded and installed before compiling and installing the test apps. | [ ] | +| enableCodeCop | If enableCodeCop is set to true, the CI/CD workflow will enable the CodeCop analyzer when building. | false | +| enableUICop | If enableUICop is set to true, the CI/CD workflow will enable the UICop analyzer when building. | false | +| customCodeCops | CustomCodeCops is an array of paths or URLs to custom Code Cop DLLs you want to enable when building. | [ ] | +| keyVaultCertificateUrlSecretName
keyVaultCertificatePasswordSecretName
keyVaultClientIdSecretName | If you want to enable KeyVault access for your AppSource App, you need to provide 3 secrets as GitHub Secrets or in the Azure KeyVault. The names of those secrets (**NOT the secrets themselves**) should be specified in the settings file with these 3 settings. Default is to not have KeyVault access from your AppSource App. Read [this](EnableKeyVaultForAppSourceApp.md) for more information. | | +| codeSignCertificateUrlSecretName
codeSignCertificatePasswordSecretName | When developing AppSource Apps, your app needs to be code signed and you need to add secrets to GitHub secrets or Azure KeyVault, specifying the secure URL from which your codesigning certificate pfx file can be downloaded and the password for this certificate. These settings specifies the names (**NOT the secrets themselves**) of the code signing certificate url and password. Default is to look for secrets called CodeSignCertificateUrl and CodeSignCertificatePassword. Read [this](SetupCiCdForExistingAppSourceApp.md) for more information. | CodeSignCertificateUrl
CodeSignCertificatePassword | | alwaysBuildAllProjects | This setting only makes sense if the repository is setup for multiple projects.
Standard behavior of the CI/CD workflow is to only build the projects, in which files have changes when running the workflow due to a push or a pull request | false | ## Expert settings (rarely used) @@ -61,8 +66,8 @@ When running a workflow or a local script, the settings are applied by reading o | Name | Description | Default value | | :-- | :-- | :-- | | repoName | the name of the repository | name of GitHub repository | -| runNumberOffset | **TODO:** document | 0 | -| applicationDependency | **TODO:** document | 19.0.0.0 | +| runNumberOffset | when using **VersioningStrategy** 0, the CI/CD workflow uses the GITHUB RUN_NUMBER as the build part of the version number as described under VersioningStrategy. The RUN_NUMBER is ever increasing and if you want to reset it, when increasing the Major or Minor parts of the version number, you can specify a negative number as runNumberOffset. You can also provide a positive number to get a starting offset. Read about RUN_NUMBER [here](https://docs.github.com/en/actions/learn-github-actions/contexts) | 0 | +| applicationDependency | Application dependency defines the lowest Business Central version supported by your app (Build will fail early if artifacts used are lower than this). The value is calculated by reading app.json for all apps, but cannot be lower than the applicationDependency setting which has a default value of 18.0.0.0 | 18.0.0.0 | | installTestRunner | Determines wheather the test runner will be installed in the pipeline. If there are testFolders in the project, this setting will be true. | calculated | | installTestFramework | Determines whether the test framework apps will be installed in the pipeline. If the test apps in the testFolders have dependencies on the test framework apps, this setting will be true | calculated | | installTestLibraries | Determines whether the test libraries apps will be installed in the pipeline. If the test apps in the testFolders have dependencies on the test library apps, this setting will be true | calculated | @@ -75,4 +80,34 @@ When running a workflow or a local script, the settings are applied by reading o # Expert level -**TODO:** Describe overrides for Run-AlPipeline +## Run-AlPipeline script override + +AL-Go for GitHub utilizes the Run-AlPipeline function from BcContaineHelper to perform the actual build (compile, publish, test etc). The Run-AlPipeline function supports overriding functions for creating containers, compiling apps and a lot of other things. + +This functionality is also available in AL-Go for GitHub, by adding a file to the .AL-Go folder, you automatically override the function. + +| Override | Description | +| :-- | :-- | +| DockerPull.ps1 | Pull the image specified by the parameter $imageName | +| NewBcContainer.ps1 | Create the container using the parameters transferred in the $parameters hashtable | +| ImportTestToolkitToBcContainer.ps1 | Import the test toolkit apps specified by the $parameters hashtable | +| CompileAppInBcContainer.ps1 | Compile the apps specified by the $parameters hashtable | +| GetBcContainerAppInfo.ps1 | Get App Info for the apps specified by the $parameters hashtable | +| PublishBcContainerApp.ps1 | Publish apps specified by the $parameters hashtable | +| UnPublishBcContainerApp.ps1 | UnPublish apps specified by the $parameters hashtable | +| InstallBcAppFromAppSource.ps1 | Install apps from AppSource specified by the $parameters hashtable | +| SignBcContainerApp.ps1 | Sign apps specified by the $parameters hashtable| +| ImportTestDataInBcContainer.ps1 | If this function is provided, it is expected to insert the test data needed for running tests | +| RunTestsInBcContainer.ps1 | Run the tests specified by the $parameters hashtable | +| GetBcContainerAppRuntimePackage.ps1 | Get the runtime package specified by the $parameters hashtable | +| RemoveBcContainer.ps1 | Cleanup based on the $parameters hashtable | + +## BcContainerHelper settings + +TODO: Repo settings file can contain BcContainerHelper settings. + +## Your own version of AL-Go for GitHub + +For experts only, following the description [here](Contributing.md) you can setup a local fork of **AL-Go for GitHub** and use that as your templates. You can fetch upstream changes from Microsoft regularly to incorporate these changes into your version and this way have your modified version of AL-Go for GitHub. + +**Note:** Our goal is to never break repositories, which are using AL-Go for GitHub as their template. We almost certainly will break you if you create local modifications to scripts and pipelines. diff --git a/Templates/AppSource App/.AL-Go/Test Current.settings.json b/Templates/AppSource App/.AL-Go/Test Current.settings.json new file mode 100644 index 00000000..89d6fb2c --- /dev/null +++ b/Templates/AppSource App/.AL-Go/Test Current.settings.json @@ -0,0 +1,6 @@ +{ + "artifact": "////latest", + "cacheImageName": "", + "appBuild": 2147483647, + "appRevision": 2147483647 +} diff --git a/Templates/AppSource App/.AL-Go/Test Next Major.settings.json b/Templates/AppSource App/.AL-Go/Test Next Major.settings.json new file mode 100644 index 00000000..49311144 --- /dev/null +++ b/Templates/AppSource App/.AL-Go/Test Next Major.settings.json @@ -0,0 +1,6 @@ +{ + "artifact": "////nextmajor/{INSIDERSASTOKEN}", + "cacheImageName": "", + "appBuild": 2147483647, + "appRevision": 2147483647 +} diff --git a/Templates/AppSource App/.AL-Go/Test Next Minor.settings.json b/Templates/AppSource App/.AL-Go/Test Next Minor.settings.json new file mode 100644 index 00000000..cefaa9a2 --- /dev/null +++ b/Templates/AppSource App/.AL-Go/Test Next Minor.settings.json @@ -0,0 +1,6 @@ +{ + "artifact": "////nextminor/{INSIDERSASTOKEN}", + "cacheImageName": "", + "appBuild": 2147483647, + "appRevision": 2147483647 +} diff --git a/Templates/AppSource App/.AL-Go/settings.json b/Templates/AppSource App/.AL-Go/settings.json index 08ead093..d1f1fa5f 100644 --- a/Templates/AppSource App/.AL-Go/settings.json +++ b/Templates/AppSource App/.AL-Go/settings.json @@ -1,7 +1,6 @@ { "type": "AppSource App", "country": "us", - "templateUrl": "https://github.com/microsoft/AL-Go-AppSource@main", "AppSourceCopMandatoryAffixes": [ "" ], diff --git a/Templates/AppSource App/.github/AL-Go-Settings.json b/Templates/AppSource App/.github/AL-Go-Settings.json new file mode 100644 index 00000000..2de7cfda --- /dev/null +++ b/Templates/AppSource App/.github/AL-Go-Settings.json @@ -0,0 +1,3 @@ +{ + "templateUrl": "https://github.com/microsoft/AL-Go-AppSource@main" +} \ No newline at end of file diff --git a/Templates/AppSource App/.github/workflows/AddExistingAppOrTestApp.yaml b/Templates/AppSource App/.github/workflows/AddExistingAppOrTestApp.yaml index 8775bb98..59ec240f 100644 --- a/Templates/AppSource App/.github/workflows/AddExistingAppOrTestApp.yaml +++ b/Templates/AppSource App/.github/workflows/AddExistingAppOrTestApp.yaml @@ -19,36 +19,36 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0090" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Add existing app uses: microsoft/AL-Go-Actions/AddExistingApp@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ github.event.inputs.project }} url: ${{ github.event.inputs.url }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0090" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/CICD.yaml b/Templates/AppSource App/.github/workflows/CICD.yaml index 254fefa9..3e7bb1f6 100644 --- a/Templates/AppSource App/.github/workflows/CICD.yaml +++ b/Templates/AppSource App/.github/workflows/CICD.yaml @@ -1,6 +1,7 @@ name: CI/CD on: + workflow_dispatch: push: paths-ignore: - 'README.md' @@ -10,26 +11,25 @@ on: paths-ignore: - 'README.md' - '.github/**' - workflow_dispatch: defaults: run: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0091" CheckForUpdates: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout uses: actions/checkout@v2 @@ -37,17 +37,17 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: TemplateUrl - name: Check for updates to AL-Go system files uses: microsoft/AL-Go-Actions/CheckForUpdates@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} templateUrl: ${{ env.TemplateUrl }} Analyze: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] outputs: projects: ${{ steps.Projects.outputs.projects }} projectCount: ${{ steps.Projects.outputs.projectCount }} @@ -148,7 +148,7 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ matrix.project }} - name: Read secrets @@ -156,14 +156,14 @@ jobs: env: secrets: ${{ toJson(secrets) }} with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} settingsJson: ${{ env.Settings }} secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' - name: Run pipeline uses: microsoft/AL-Go-Actions/RunPipeline@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} Project: ${{ matrix.project }} settingsJson: ${{ env.Settings }} SecretsJson: ${{ env.RepoSecrets }} @@ -210,12 +210,12 @@ jobs: if: always() uses: microsoft/AL-Go-Actions/PipelineCleanup@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} Project: ${{ matrix.project }} Deploy: runs-on: [ windows-latest ] needs: [ Analyze, Build ] - if: ${{ needs.Analyze.outputs.environmentCount > 0 }} + if: ${{ github.event_name != 'pull request' && needs.Analyze.outputs.environmentCount > 0 }} strategy: matrix: environment: ${{ fromJson(needs.Analyze.outputs.environments) }} @@ -279,14 +279,14 @@ jobs: environmentName: ${{ matrix.environment }} artifacts: '${{ github.workspace }}\artifacts' - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, Analyze, Build, Deploy ] + needs: [ Initialization, Analyze, Build, Deploy ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0091" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/CreateApp.yaml b/Templates/AppSource App/.github/workflows/CreateApp.yaml index 53c7dbe9..4fe0d082 100644 --- a/Templates/AppSource App/.github/workflows/CreateApp.yaml +++ b/Templates/AppSource App/.github/workflows/CreateApp.yaml @@ -25,19 +25,19 @@ defaults: run: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0092" - createApp: + CreateApp: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout uses: actions/checkout@v2 @@ -45,7 +45,7 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: type - name: Creating a new app @@ -57,16 +57,16 @@ jobs: publisher: ${{ github.event.inputs.publisher }} idrange: ${{ github.event.inputs.idrange }} directCommit: ${{ github.event.inputs.directCommit }} - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, createApp ] + needs: [ Initialization, CreateApp ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0092" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} \ No newline at end of file + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml b/Templates/AppSource App/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml index 04ae94da..1458b128 100644 --- a/Templates/AppSource App/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml +++ b/Templates/AppSource App/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml @@ -20,19 +20,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0093" CreateEnvironment: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout @@ -41,14 +41,14 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} - name: Read secrets uses: microsoft/AL-Go-Actions/ReadSecrets@main env: secrets: ${{ toJson(secrets) }} with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} settingsJson: ${{ env.Settings }} secrets: 'adminCenterApiCredentials' @@ -74,19 +74,19 @@ jobs: - name: Create Development Environment uses: microsoft/AL-Go-Actions/CreateDevelopmentEnvironment@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} environmentName: ${{ github.event.inputs.environmentName }} reUseExistingEnvironment: ${{ github.event.inputs.reUseExistingEnvironment }} adminCenterApiCredentials: ${{ env.adminCenterApiCredentials }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, CreateEnvironment ] + needs: [ Initialization, CreateEnvironment ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0093" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/CreateRelease.yaml b/Templates/AppSource App/.github/workflows/CreateRelease.yaml index b51f0451..bbdedd18 100644 --- a/Templates/AppSource App/.github/workflows/CreateRelease.yaml +++ b/Templates/AppSource App/.github/workflows/CreateRelease.yaml @@ -31,19 +31,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0094" CreateRelease: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] outputs: artifacts: ${{ steps.analyzeartifacts.outputs.artifacts }} upload_url: ${{ steps.createrelease.outputs.upload_url }} @@ -54,13 +54,13 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: TemplateUrl - name: Check for updates to AL-Go system files uses: microsoft/AL-Go-Actions/CheckForUpdates@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} templateUrl: ${{ env.TemplateUrl }} - name: Analyze Artifacts @@ -95,7 +95,7 @@ jobs: id: createreleasenotes uses: microsoft/AL-Go-Actions/CreateReleaseNotes@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} tag_name: '${{github.event.inputs.tag}}' - name: Create release @@ -136,14 +136,14 @@ jobs: asset_name: '${{ matrix.name }}.zip' asset_content_type: application/zip - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, CreateRelease, UploadArtifacts ] + needs: [ Initialization, CreateRelease, UploadArtifacts ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0094" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} \ No newline at end of file + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/CreateTestApp.yaml b/Templates/AppSource App/.github/workflows/CreateTestApp.yaml index 0a2597e7..e0020ba3 100644 --- a/Templates/AppSource App/.github/workflows/CreateTestApp.yaml +++ b/Templates/AppSource App/.github/workflows/CreateTestApp.yaml @@ -28,25 +28,25 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0095" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Creating a new test app uses: microsoft/AL-Go-Actions/CreateApp@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ github.event.inputs.project }} type: 'Test App' publisher: ${{ github.event.inputs.publisher }} @@ -54,14 +54,14 @@ jobs: idrange: ${{ github.event.inputs.idrange }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0095" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/Current.yaml b/Templates/AppSource App/.github/workflows/Current.yaml new file mode 100644 index 00000000..89a4b806 --- /dev/null +++ b/Templates/AppSource App/.github/workflows/Current.yaml @@ -0,0 +1,157 @@ +name: Test Current + +on: + workflow_dispatch: + +defaults: + run: + shell: PowerShell + +jobs: + Initialization: + runs-on: [ windows-latest ] + outputs: + telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} + steps: + - id: init + uses: microsoft/AL-Go-Actions/WorkflowInitialize@main + with: + eventId: "DO0100" + + Analyze: + runs-on: [ windows-latest ] + needs: [ Initialization ] + outputs: + projects: ${{ steps.Projects.outputs.projects }} + projectCount: ${{ steps.Projects.outputs.projectCount }} + githubRunner: ${{ steps.OutputSettings.outputs.githubRunner }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + get: githubRunner,alwaysBuildAllProjects + + - name: Output settings + id: OutputSettings + run: | + $gitHubRunner = "$env:githubRunner".Split(',') | ConvertTo-Json -compress + Write-Host "::set-output name=githubRunner::$githubRunner" + Write-Host "set-output name=githubRunner::$githubRunner" + + - name: Projects + id: Projects + run: | + if (Test-Path ".AL-Go" -PathType Container) { + $projects = @(".") + } + else { + $projects = @(Get-ChildItem -Path $ENV:GITHUB_WORKSPACE -Directory | Where-Object { Test-Path (Join-Path $_.FullName ".AL-Go") -PathType Container } | ForEach-Object { $_.Name }) + Write-Host "Projects: $($projects -join ', ')" + if (!($ENV:GITHUB_EVENT_NAME -eq "workflow_dispatch" -or "$ENV:alwaysBuildAllProjects" -eq "true")) { + $headers = @{ + "Authorization" = "token ${{ github.token }}" + "Accept" = "application/vnd.github.baptiste-preview+json" + } + if ($ENV:GITHUB_EVENT_NAME -eq "pull_request") { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.pull_request.base.sha }}...${{ github.sha }}" + } + else { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.before }}...${{ github.event.after }}" + } + $response = Invoke-WebRequest -Headers $headers -UseBasicParsing -Method GET -Uri $url | ConvertFrom-Json + $filesChanged = @($response.files | ForEach-Object { $_.filename }) + if ($filesChanged.Count -lt 250) { + $foldersChanged = @($filesChanged | ForEach-Object { $_.Split('/')[0] } | Select-Object -Unique) + $projects = @($projects | Where-Object { $foldersChanged -contains $_ }) + Write-Host "Modified projects: $($projects -join ', ')" + } + } + } + if ($projects.Count -eq 1) { + $projectsJSon = "[$($projects | ConvertTo-Json -compress)]" + } + else { + $projectsJSon = $projects | ConvertTo-Json -compress + } + Write-Host "::set-output name=projects::$projectsJson" + Write-Host "::set-output name=projectCount::$($projects.Count)" + Write-Host "set-output name=projects::$projectsJson" + Write-Host "set-output name=projectCount::$($projects.Count)" + + Build: + needs: [ Analyze ] + runs-on: ${{ fromJson(needs.Analyze.outputs.githubRunner) }} + strategy: + matrix: + project: ${{ fromJson(needs.Analyze.outputs.projects) }} + fail-fast: false + name: Build ${{ matrix.project }} + outputs: + TestResultsArtifactsName: ${{ steps.calculateArtifactNames.outputs.TestResultsArtifactsName }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + project: ${{ matrix.project }} + + - name: Read secrets + uses: microsoft/AL-Go-Actions/ReadSecrets@main + env: + secrets: ${{ toJson(secrets) }} + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + settingsJson: ${{ env.Settings }} + secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' + + - name: Run pipeline + uses: microsoft/AL-Go-Actions/RunPipeline@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + settingsJson: ${{ env.Settings }} + SecretsJson: ${{ env.RepoSecrets }} + + - name: Calculate Artifact names + id: calculateArtifactNames + if: success() || failure() + run: | + $settings = '${{ env.Settings }}' | ConvertFrom-Json + $project = '${{ matrix.project }}' + if ($project -eq ".") { $project = $settings.RepoName } + $TestResultsArtifactsName = "$project-TestResults" + Write-Host "::set-output name=TestResultsArtifactsName::$TestResultsArtifactsName" + Add-Content -Path $env:GITHUB_ENV -Value "TestResultsArtifactsName=$TestResultsArtifactsName" + + - name: Publish artifacts - test results + uses: actions/upload-artifact@v2 + if: success() || failure() + with: + name: ${{ env.testResultsArtifactsName }} + path: '${{ matrix.project }}/TestResults.xml' + if-no-files-found: ignore + + - name: Cleanup + if: always() + uses: microsoft/AL-Go-Actions/PipelineCleanup@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + + PostProcess: + if: always() + runs-on: [ windows-latest ] + needs: [ Initialization, Analyze, Build ] + steps: + - name: Finalizing the workflow + id: PostProcess + uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main + with: + eventId: "DO0100" + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/IncrementVersionNumber.yaml b/Templates/AppSource App/.github/workflows/IncrementVersionNumber.yaml index cd277163..58f4d8fe 100644 --- a/Templates/AppSource App/.github/workflows/IncrementVersionNumber.yaml +++ b/Templates/AppSource App/.github/workflows/IncrementVersionNumber.yaml @@ -20,37 +20,37 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0096" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Increment Version Number uses: microsoft/AL-Go-Actions/IncrementVersionNumber@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ github.event.inputs.project }} versionNumber: ${{ github.event.inputs.versionNumber }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0096" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/NextMajor.yaml b/Templates/AppSource App/.github/workflows/NextMajor.yaml new file mode 100644 index 00000000..f88888fe --- /dev/null +++ b/Templates/AppSource App/.github/workflows/NextMajor.yaml @@ -0,0 +1,157 @@ +name: Test Next Major + +on: + workflow_dispatch: + +defaults: + run: + shell: PowerShell + +jobs: + Initialization: + runs-on: [ windows-latest ] + outputs: + telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} + steps: + - id: init + uses: microsoft/AL-Go-Actions/WorkflowInitialize@main + with: + eventId: "DO0099" + + Analyze: + runs-on: [ windows-latest ] + needs: [ Initialization ] + outputs: + projects: ${{ steps.Projects.outputs.projects }} + projectCount: ${{ steps.Projects.outputs.projectCount }} + githubRunner: ${{ steps.OutputSettings.outputs.githubRunner }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + get: githubRunner,alwaysBuildAllProjects + + - name: Output settings + id: OutputSettings + run: | + $gitHubRunner = "$env:githubRunner".Split(',') | ConvertTo-Json -compress + Write-Host "::set-output name=githubRunner::$githubRunner" + Write-Host "set-output name=githubRunner::$githubRunner" + + - name: Projects + id: Projects + run: | + if (Test-Path ".AL-Go" -PathType Container) { + $projects = @(".") + } + else { + $projects = @(Get-ChildItem -Path $ENV:GITHUB_WORKSPACE -Directory | Where-Object { Test-Path (Join-Path $_.FullName ".AL-Go") -PathType Container } | ForEach-Object { $_.Name }) + Write-Host "Projects: $($projects -join ', ')" + if (!($ENV:GITHUB_EVENT_NAME -eq "workflow_dispatch" -or "$ENV:alwaysBuildAllProjects" -eq "true")) { + $headers = @{ + "Authorization" = "token ${{ github.token }}" + "Accept" = "application/vnd.github.baptiste-preview+json" + } + if ($ENV:GITHUB_EVENT_NAME -eq "pull_request") { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.pull_request.base.sha }}...${{ github.sha }}" + } + else { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.before }}...${{ github.event.after }}" + } + $response = Invoke-WebRequest -Headers $headers -UseBasicParsing -Method GET -Uri $url | ConvertFrom-Json + $filesChanged = @($response.files | ForEach-Object { $_.filename }) + if ($filesChanged.Count -lt 250) { + $foldersChanged = @($filesChanged | ForEach-Object { $_.Split('/')[0] } | Select-Object -Unique) + $projects = @($projects | Where-Object { $foldersChanged -contains $_ }) + Write-Host "Modified projects: $($projects -join ', ')" + } + } + } + if ($projects.Count -eq 1) { + $projectsJSon = "[$($projects | ConvertTo-Json -compress)]" + } + else { + $projectsJSon = $projects | ConvertTo-Json -compress + } + Write-Host "::set-output name=projects::$projectsJson" + Write-Host "::set-output name=projectCount::$($projects.Count)" + Write-Host "set-output name=projects::$projectsJson" + Write-Host "set-output name=projectCount::$($projects.Count)" + + Build: + needs: [ Analyze ] + runs-on: ${{ fromJson(needs.Analyze.outputs.githubRunner) }} + strategy: + matrix: + project: ${{ fromJson(needs.Analyze.outputs.projects) }} + fail-fast: false + name: Build ${{ matrix.project }} + outputs: + TestResultsArtifactsName: ${{ steps.calculateArtifactNames.outputs.TestResultsArtifactsName }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + project: ${{ matrix.project }} + + - name: Read secrets + uses: microsoft/AL-Go-Actions/ReadSecrets@main + env: + secrets: ${{ toJson(secrets) }} + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + settingsJson: ${{ env.Settings }} + secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' + + - name: Run pipeline + uses: microsoft/AL-Go-Actions/RunPipeline@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + settingsJson: ${{ env.Settings }} + SecretsJson: ${{ env.RepoSecrets }} + + - name: Calculate Artifact names + id: calculateArtifactNames + if: success() || failure() + run: | + $settings = '${{ env.Settings }}' | ConvertFrom-Json + $project = '${{ matrix.project }}' + if ($project -eq ".") { $project = $settings.RepoName } + $TestResultsArtifactsName = "$project-TestResults" + Write-Host "::set-output name=TestResultsArtifactsName::$TestResultsArtifactsName" + Add-Content -Path $env:GITHUB_ENV -Value "TestResultsArtifactsName=$TestResultsArtifactsName" + + - name: Publish artifacts - test results + uses: actions/upload-artifact@v2 + if: success() || failure() + with: + name: ${{ env.testResultsArtifactsName }} + path: '${{ matrix.project }}/TestResults.xml' + if-no-files-found: ignore + + - name: Cleanup + if: always() + uses: microsoft/AL-Go-Actions/PipelineCleanup@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + + PostProcess: + if: always() + runs-on: [ windows-latest ] + needs: [ Initialization, Analyze, Build ] + steps: + - name: Finalizing the workflow + id: PostProcess + uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main + with: + eventId: "DO0099" + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/NextMinor.yaml b/Templates/AppSource App/.github/workflows/NextMinor.yaml new file mode 100644 index 00000000..15a26f48 --- /dev/null +++ b/Templates/AppSource App/.github/workflows/NextMinor.yaml @@ -0,0 +1,157 @@ +name: Test Next Minor + +on: + workflow_dispatch: + +defaults: + run: + shell: PowerShell + +jobs: + Initialization: + runs-on: [ windows-latest ] + outputs: + telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} + steps: + - id: init + uses: microsoft/AL-Go-Actions/WorkflowInitialize@main + with: + eventId: "DO0100" + + Analyze: + runs-on: [ windows-latest ] + needs: [ Initialization ] + outputs: + projects: ${{ steps.Projects.outputs.projects }} + projectCount: ${{ steps.Projects.outputs.projectCount }} + githubRunner: ${{ steps.OutputSettings.outputs.githubRunner }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + get: githubRunner,alwaysBuildAllProjects + + - name: Output settings + id: OutputSettings + run: | + $gitHubRunner = "$env:githubRunner".Split(',') | ConvertTo-Json -compress + Write-Host "::set-output name=githubRunner::$githubRunner" + Write-Host "set-output name=githubRunner::$githubRunner" + + - name: Projects + id: Projects + run: | + if (Test-Path ".AL-Go" -PathType Container) { + $projects = @(".") + } + else { + $projects = @(Get-ChildItem -Path $ENV:GITHUB_WORKSPACE -Directory | Where-Object { Test-Path (Join-Path $_.FullName ".AL-Go") -PathType Container } | ForEach-Object { $_.Name }) + Write-Host "Projects: $($projects -join ', ')" + if (!($ENV:GITHUB_EVENT_NAME -eq "workflow_dispatch" -or "$ENV:alwaysBuildAllProjects" -eq "true")) { + $headers = @{ + "Authorization" = "token ${{ github.token }}" + "Accept" = "application/vnd.github.baptiste-preview+json" + } + if ($ENV:GITHUB_EVENT_NAME -eq "pull_request") { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.pull_request.base.sha }}...${{ github.sha }}" + } + else { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.before }}...${{ github.event.after }}" + } + $response = Invoke-WebRequest -Headers $headers -UseBasicParsing -Method GET -Uri $url | ConvertFrom-Json + $filesChanged = @($response.files | ForEach-Object { $_.filename }) + if ($filesChanged.Count -lt 250) { + $foldersChanged = @($filesChanged | ForEach-Object { $_.Split('/')[0] } | Select-Object -Unique) + $projects = @($projects | Where-Object { $foldersChanged -contains $_ }) + Write-Host "Modified projects: $($projects -join ', ')" + } + } + } + if ($projects.Count -eq 1) { + $projectsJSon = "[$($projects | ConvertTo-Json -compress)]" + } + else { + $projectsJSon = $projects | ConvertTo-Json -compress + } + Write-Host "::set-output name=projects::$projectsJson" + Write-Host "::set-output name=projectCount::$($projects.Count)" + Write-Host "set-output name=projects::$projectsJson" + Write-Host "set-output name=projectCount::$($projects.Count)" + + Build: + needs: [ Analyze ] + runs-on: ${{ fromJson(needs.Analyze.outputs.githubRunner) }} + strategy: + matrix: + project: ${{ fromJson(needs.Analyze.outputs.projects) }} + fail-fast: false + name: Build ${{ matrix.project }} + outputs: + TestResultsArtifactsName: ${{ steps.calculateArtifactNames.outputs.TestResultsArtifactsName }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + project: ${{ matrix.project }} + + - name: Read secrets + uses: microsoft/AL-Go-Actions/ReadSecrets@main + env: + secrets: ${{ toJson(secrets) }} + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + settingsJson: ${{ env.Settings }} + secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' + + - name: Run pipeline + uses: microsoft/AL-Go-Actions/RunPipeline@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + settingsJson: ${{ env.Settings }} + SecretsJson: ${{ env.RepoSecrets }} + + - name: Calculate Artifact names + id: calculateArtifactNames + if: success() || failure() + run: | + $settings = '${{ env.Settings }}' | ConvertFrom-Json + $project = '${{ matrix.project }}' + if ($project -eq ".") { $project = $settings.RepoName } + $TestResultsArtifactsName = "$project-TestResults" + Write-Host "::set-output name=TestResultsArtifactsName::$TestResultsArtifactsName" + Add-Content -Path $env:GITHUB_ENV -Value "TestResultsArtifactsName=$TestResultsArtifactsName" + + - name: Publish artifacts - test results + uses: actions/upload-artifact@v2 + if: success() || failure() + with: + name: ${{ env.testResultsArtifactsName }} + path: '${{ matrix.project }}/TestResults.xml' + if-no-files-found: ignore + + - name: Cleanup + if: always() + uses: microsoft/AL-Go-Actions/PipelineCleanup@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + + PostProcess: + if: always() + runs-on: [ windows-latest ] + needs: [ Initialization, Analyze, Build ] + steps: + - name: Finalizing the workflow + id: PostProcess + uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main + with: + eventId: "DO0100" + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/PublishToEnvironment.yaml b/Templates/AppSource App/.github/workflows/PublishToEnvironment.yaml index cd1feab9..27b4fb11 100644 --- a/Templates/AppSource App/.github/workflows/PublishToEnvironment.yaml +++ b/Templates/AppSource App/.github/workflows/PublishToEnvironment.yaml @@ -17,19 +17,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0097" Analyze: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] outputs: environments: ${{ steps.Environments.outputs.environments }} environmentCount: ${{ steps.Environments.outputs.environmentCount }} @@ -112,21 +112,20 @@ jobs: env: authContext: '${{ steps.authContext.outputs.authContext }}' with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} type: 'Publish' projects: '${{ secrets.Projects }}' environmentName: ${{ matrix.environment }} artifacts: ${{ github.event.inputs.appVersion }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, Environments, Deploy ] + needs: [ Initialization, Analyze, Deploy ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0097" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} - + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/AppSource App/.github/workflows/UpdateGitHubGoSystemFiles.yaml b/Templates/AppSource App/.github/workflows/UpdateGitHubGoSystemFiles.yaml index d678ffc7..a751b126 100644 --- a/Templates/AppSource App/.github/workflows/UpdateGitHubGoSystemFiles.yaml +++ b/Templates/AppSource App/.github/workflows/UpdateGitHubGoSystemFiles.yaml @@ -17,19 +17,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0098" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout @@ -38,7 +38,7 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: KeyVaultName,GhTokenWorkflowSecretName,TemplateUrl - name: Read secrets @@ -46,7 +46,7 @@ jobs: env: secrets: ${{ toJson(secrets) }} with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} settingsJson: ${{ env.Settings }} secrets: 'ghTokenWorkflow=${{ env.GHTOKENWORKFLOWSECRETNAME }}' @@ -61,20 +61,20 @@ jobs: - name: Update AL-Go system files uses: microsoft/AL-Go-Actions/CheckForUpdates@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} token: ${{ env.ghTokenWorkflow }} - update: Y + Update: Y templateUrl: ${{ env.TemplateUrl }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0098" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} \ No newline at end of file + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.AL-Go/Test Current.settings.json b/Templates/Per Tenant Extension/.AL-Go/Test Current.settings.json new file mode 100644 index 00000000..89d6fb2c --- /dev/null +++ b/Templates/Per Tenant Extension/.AL-Go/Test Current.settings.json @@ -0,0 +1,6 @@ +{ + "artifact": "////latest", + "cacheImageName": "", + "appBuild": 2147483647, + "appRevision": 2147483647 +} diff --git a/Templates/Per Tenant Extension/.AL-Go/Test Next Major.settings.json b/Templates/Per Tenant Extension/.AL-Go/Test Next Major.settings.json new file mode 100644 index 00000000..49311144 --- /dev/null +++ b/Templates/Per Tenant Extension/.AL-Go/Test Next Major.settings.json @@ -0,0 +1,6 @@ +{ + "artifact": "////nextmajor/{INSIDERSASTOKEN}", + "cacheImageName": "", + "appBuild": 2147483647, + "appRevision": 2147483647 +} diff --git a/Templates/Per Tenant Extension/.AL-Go/Test Next Minor.settings.json b/Templates/Per Tenant Extension/.AL-Go/Test Next Minor.settings.json new file mode 100644 index 00000000..cefaa9a2 --- /dev/null +++ b/Templates/Per Tenant Extension/.AL-Go/Test Next Minor.settings.json @@ -0,0 +1,6 @@ +{ + "artifact": "////nextminor/{INSIDERSASTOKEN}", + "cacheImageName": "", + "appBuild": 2147483647, + "appRevision": 2147483647 +} diff --git a/Templates/Per Tenant Extension/.AL-Go/settings.json b/Templates/Per Tenant Extension/.AL-Go/settings.json index 36768fbf..946e692c 100644 --- a/Templates/Per Tenant Extension/.AL-Go/settings.json +++ b/Templates/Per Tenant Extension/.AL-Go/settings.json @@ -1,7 +1,6 @@ { "type": "PTE", "country": "us", - "templateUrl": "https://github.com/microsoft/AL-Go-PTE@main", "appFolders": [ ], "testFolders": [ diff --git a/Templates/Per Tenant Extension/.github/AL-Go-Settings.json b/Templates/Per Tenant Extension/.github/AL-Go-Settings.json new file mode 100644 index 00000000..474143ac --- /dev/null +++ b/Templates/Per Tenant Extension/.github/AL-Go-Settings.json @@ -0,0 +1,3 @@ +{ + "templateUrl": "https://github.com/microsoft/AL-Go-PTE@main" +} diff --git a/Templates/Per Tenant Extension/.github/workflows/AddExistingAppOrTestApp.yaml b/Templates/Per Tenant Extension/.github/workflows/AddExistingAppOrTestApp.yaml index 8775bb98..59ec240f 100644 --- a/Templates/Per Tenant Extension/.github/workflows/AddExistingAppOrTestApp.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/AddExistingAppOrTestApp.yaml @@ -19,36 +19,36 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0090" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Add existing app uses: microsoft/AL-Go-Actions/AddExistingApp@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ github.event.inputs.project }} url: ${{ github.event.inputs.url }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0090" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/CICD.yaml b/Templates/Per Tenant Extension/.github/workflows/CICD.yaml index 254fefa9..3e7bb1f6 100644 --- a/Templates/Per Tenant Extension/.github/workflows/CICD.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/CICD.yaml @@ -1,6 +1,7 @@ name: CI/CD on: + workflow_dispatch: push: paths-ignore: - 'README.md' @@ -10,26 +11,25 @@ on: paths-ignore: - 'README.md' - '.github/**' - workflow_dispatch: defaults: run: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0091" CheckForUpdates: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout uses: actions/checkout@v2 @@ -37,17 +37,17 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: TemplateUrl - name: Check for updates to AL-Go system files uses: microsoft/AL-Go-Actions/CheckForUpdates@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} templateUrl: ${{ env.TemplateUrl }} Analyze: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] outputs: projects: ${{ steps.Projects.outputs.projects }} projectCount: ${{ steps.Projects.outputs.projectCount }} @@ -148,7 +148,7 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ matrix.project }} - name: Read secrets @@ -156,14 +156,14 @@ jobs: env: secrets: ${{ toJson(secrets) }} with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} settingsJson: ${{ env.Settings }} secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' - name: Run pipeline uses: microsoft/AL-Go-Actions/RunPipeline@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} Project: ${{ matrix.project }} settingsJson: ${{ env.Settings }} SecretsJson: ${{ env.RepoSecrets }} @@ -210,12 +210,12 @@ jobs: if: always() uses: microsoft/AL-Go-Actions/PipelineCleanup@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} Project: ${{ matrix.project }} Deploy: runs-on: [ windows-latest ] needs: [ Analyze, Build ] - if: ${{ needs.Analyze.outputs.environmentCount > 0 }} + if: ${{ github.event_name != 'pull request' && needs.Analyze.outputs.environmentCount > 0 }} strategy: matrix: environment: ${{ fromJson(needs.Analyze.outputs.environments) }} @@ -279,14 +279,14 @@ jobs: environmentName: ${{ matrix.environment }} artifacts: '${{ github.workspace }}\artifacts' - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, Analyze, Build, Deploy ] + needs: [ Initialization, Analyze, Build, Deploy ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0091" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/CreateApp.yaml b/Templates/Per Tenant Extension/.github/workflows/CreateApp.yaml index 53c7dbe9..4fe0d082 100644 --- a/Templates/Per Tenant Extension/.github/workflows/CreateApp.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/CreateApp.yaml @@ -25,19 +25,19 @@ defaults: run: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0092" - createApp: + CreateApp: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout uses: actions/checkout@v2 @@ -45,7 +45,7 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: type - name: Creating a new app @@ -57,16 +57,16 @@ jobs: publisher: ${{ github.event.inputs.publisher }} idrange: ${{ github.event.inputs.idrange }} directCommit: ${{ github.event.inputs.directCommit }} - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, createApp ] + needs: [ Initialization, CreateApp ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0092" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} \ No newline at end of file + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml b/Templates/Per Tenant Extension/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml index 04ae94da..1458b128 100644 --- a/Templates/Per Tenant Extension/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/CreateOnlineDevelopmentEnvironment.yaml @@ -20,19 +20,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0093" CreateEnvironment: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout @@ -41,14 +41,14 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} - name: Read secrets uses: microsoft/AL-Go-Actions/ReadSecrets@main env: secrets: ${{ toJson(secrets) }} with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} settingsJson: ${{ env.Settings }} secrets: 'adminCenterApiCredentials' @@ -74,19 +74,19 @@ jobs: - name: Create Development Environment uses: microsoft/AL-Go-Actions/CreateDevelopmentEnvironment@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} environmentName: ${{ github.event.inputs.environmentName }} reUseExistingEnvironment: ${{ github.event.inputs.reUseExistingEnvironment }} adminCenterApiCredentials: ${{ env.adminCenterApiCredentials }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, CreateEnvironment ] + needs: [ Initialization, CreateEnvironment ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0093" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/CreateRelease.yaml b/Templates/Per Tenant Extension/.github/workflows/CreateRelease.yaml index b51f0451..bbdedd18 100644 --- a/Templates/Per Tenant Extension/.github/workflows/CreateRelease.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/CreateRelease.yaml @@ -31,19 +31,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0094" CreateRelease: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] outputs: artifacts: ${{ steps.analyzeartifacts.outputs.artifacts }} upload_url: ${{ steps.createrelease.outputs.upload_url }} @@ -54,13 +54,13 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: TemplateUrl - name: Check for updates to AL-Go system files uses: microsoft/AL-Go-Actions/CheckForUpdates@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} templateUrl: ${{ env.TemplateUrl }} - name: Analyze Artifacts @@ -95,7 +95,7 @@ jobs: id: createreleasenotes uses: microsoft/AL-Go-Actions/CreateReleaseNotes@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} tag_name: '${{github.event.inputs.tag}}' - name: Create release @@ -136,14 +136,14 @@ jobs: asset_name: '${{ matrix.name }}.zip' asset_content_type: application/zip - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, CreateRelease, UploadArtifacts ] + needs: [ Initialization, CreateRelease, UploadArtifacts ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0094" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} \ No newline at end of file + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/CreateTestApp.yaml b/Templates/Per Tenant Extension/.github/workflows/CreateTestApp.yaml index 0a2597e7..e0020ba3 100644 --- a/Templates/Per Tenant Extension/.github/workflows/CreateTestApp.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/CreateTestApp.yaml @@ -28,25 +28,25 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0095" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Creating a new test app uses: microsoft/AL-Go-Actions/CreateApp@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ github.event.inputs.project }} type: 'Test App' publisher: ${{ github.event.inputs.publisher }} @@ -54,14 +54,14 @@ jobs: idrange: ${{ github.event.inputs.idrange }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0095" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/Current.yaml b/Templates/Per Tenant Extension/.github/workflows/Current.yaml new file mode 100644 index 00000000..89a4b806 --- /dev/null +++ b/Templates/Per Tenant Extension/.github/workflows/Current.yaml @@ -0,0 +1,157 @@ +name: Test Current + +on: + workflow_dispatch: + +defaults: + run: + shell: PowerShell + +jobs: + Initialization: + runs-on: [ windows-latest ] + outputs: + telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} + steps: + - id: init + uses: microsoft/AL-Go-Actions/WorkflowInitialize@main + with: + eventId: "DO0100" + + Analyze: + runs-on: [ windows-latest ] + needs: [ Initialization ] + outputs: + projects: ${{ steps.Projects.outputs.projects }} + projectCount: ${{ steps.Projects.outputs.projectCount }} + githubRunner: ${{ steps.OutputSettings.outputs.githubRunner }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + get: githubRunner,alwaysBuildAllProjects + + - name: Output settings + id: OutputSettings + run: | + $gitHubRunner = "$env:githubRunner".Split(',') | ConvertTo-Json -compress + Write-Host "::set-output name=githubRunner::$githubRunner" + Write-Host "set-output name=githubRunner::$githubRunner" + + - name: Projects + id: Projects + run: | + if (Test-Path ".AL-Go" -PathType Container) { + $projects = @(".") + } + else { + $projects = @(Get-ChildItem -Path $ENV:GITHUB_WORKSPACE -Directory | Where-Object { Test-Path (Join-Path $_.FullName ".AL-Go") -PathType Container } | ForEach-Object { $_.Name }) + Write-Host "Projects: $($projects -join ', ')" + if (!($ENV:GITHUB_EVENT_NAME -eq "workflow_dispatch" -or "$ENV:alwaysBuildAllProjects" -eq "true")) { + $headers = @{ + "Authorization" = "token ${{ github.token }}" + "Accept" = "application/vnd.github.baptiste-preview+json" + } + if ($ENV:GITHUB_EVENT_NAME -eq "pull_request") { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.pull_request.base.sha }}...${{ github.sha }}" + } + else { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.before }}...${{ github.event.after }}" + } + $response = Invoke-WebRequest -Headers $headers -UseBasicParsing -Method GET -Uri $url | ConvertFrom-Json + $filesChanged = @($response.files | ForEach-Object { $_.filename }) + if ($filesChanged.Count -lt 250) { + $foldersChanged = @($filesChanged | ForEach-Object { $_.Split('/')[0] } | Select-Object -Unique) + $projects = @($projects | Where-Object { $foldersChanged -contains $_ }) + Write-Host "Modified projects: $($projects -join ', ')" + } + } + } + if ($projects.Count -eq 1) { + $projectsJSon = "[$($projects | ConvertTo-Json -compress)]" + } + else { + $projectsJSon = $projects | ConvertTo-Json -compress + } + Write-Host "::set-output name=projects::$projectsJson" + Write-Host "::set-output name=projectCount::$($projects.Count)" + Write-Host "set-output name=projects::$projectsJson" + Write-Host "set-output name=projectCount::$($projects.Count)" + + Build: + needs: [ Analyze ] + runs-on: ${{ fromJson(needs.Analyze.outputs.githubRunner) }} + strategy: + matrix: + project: ${{ fromJson(needs.Analyze.outputs.projects) }} + fail-fast: false + name: Build ${{ matrix.project }} + outputs: + TestResultsArtifactsName: ${{ steps.calculateArtifactNames.outputs.TestResultsArtifactsName }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + project: ${{ matrix.project }} + + - name: Read secrets + uses: microsoft/AL-Go-Actions/ReadSecrets@main + env: + secrets: ${{ toJson(secrets) }} + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + settingsJson: ${{ env.Settings }} + secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' + + - name: Run pipeline + uses: microsoft/AL-Go-Actions/RunPipeline@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + settingsJson: ${{ env.Settings }} + SecretsJson: ${{ env.RepoSecrets }} + + - name: Calculate Artifact names + id: calculateArtifactNames + if: success() || failure() + run: | + $settings = '${{ env.Settings }}' | ConvertFrom-Json + $project = '${{ matrix.project }}' + if ($project -eq ".") { $project = $settings.RepoName } + $TestResultsArtifactsName = "$project-TestResults" + Write-Host "::set-output name=TestResultsArtifactsName::$TestResultsArtifactsName" + Add-Content -Path $env:GITHUB_ENV -Value "TestResultsArtifactsName=$TestResultsArtifactsName" + + - name: Publish artifacts - test results + uses: actions/upload-artifact@v2 + if: success() || failure() + with: + name: ${{ env.testResultsArtifactsName }} + path: '${{ matrix.project }}/TestResults.xml' + if-no-files-found: ignore + + - name: Cleanup + if: always() + uses: microsoft/AL-Go-Actions/PipelineCleanup@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + + PostProcess: + if: always() + runs-on: [ windows-latest ] + needs: [ Initialization, Analyze, Build ] + steps: + - name: Finalizing the workflow + id: PostProcess + uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main + with: + eventId: "DO0100" + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/IncrementVersionNumber.yaml b/Templates/Per Tenant Extension/.github/workflows/IncrementVersionNumber.yaml index cd277163..9c63e599 100644 --- a/Templates/Per Tenant Extension/.github/workflows/IncrementVersionNumber.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/IncrementVersionNumber.yaml @@ -20,37 +20,38 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0096" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Increment Version Number uses: microsoft/AL-Go-Actions/IncrementVersionNumber@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} project: ${{ github.event.inputs.project }} versionNumber: ${{ github.event.inputs.versionNumber }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0096" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + diff --git a/Templates/Per Tenant Extension/.github/workflows/NextMajor.yaml b/Templates/Per Tenant Extension/.github/workflows/NextMajor.yaml new file mode 100644 index 00000000..f88888fe --- /dev/null +++ b/Templates/Per Tenant Extension/.github/workflows/NextMajor.yaml @@ -0,0 +1,157 @@ +name: Test Next Major + +on: + workflow_dispatch: + +defaults: + run: + shell: PowerShell + +jobs: + Initialization: + runs-on: [ windows-latest ] + outputs: + telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} + steps: + - id: init + uses: microsoft/AL-Go-Actions/WorkflowInitialize@main + with: + eventId: "DO0099" + + Analyze: + runs-on: [ windows-latest ] + needs: [ Initialization ] + outputs: + projects: ${{ steps.Projects.outputs.projects }} + projectCount: ${{ steps.Projects.outputs.projectCount }} + githubRunner: ${{ steps.OutputSettings.outputs.githubRunner }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + get: githubRunner,alwaysBuildAllProjects + + - name: Output settings + id: OutputSettings + run: | + $gitHubRunner = "$env:githubRunner".Split(',') | ConvertTo-Json -compress + Write-Host "::set-output name=githubRunner::$githubRunner" + Write-Host "set-output name=githubRunner::$githubRunner" + + - name: Projects + id: Projects + run: | + if (Test-Path ".AL-Go" -PathType Container) { + $projects = @(".") + } + else { + $projects = @(Get-ChildItem -Path $ENV:GITHUB_WORKSPACE -Directory | Where-Object { Test-Path (Join-Path $_.FullName ".AL-Go") -PathType Container } | ForEach-Object { $_.Name }) + Write-Host "Projects: $($projects -join ', ')" + if (!($ENV:GITHUB_EVENT_NAME -eq "workflow_dispatch" -or "$ENV:alwaysBuildAllProjects" -eq "true")) { + $headers = @{ + "Authorization" = "token ${{ github.token }}" + "Accept" = "application/vnd.github.baptiste-preview+json" + } + if ($ENV:GITHUB_EVENT_NAME -eq "pull_request") { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.pull_request.base.sha }}...${{ github.sha }}" + } + else { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.before }}...${{ github.event.after }}" + } + $response = Invoke-WebRequest -Headers $headers -UseBasicParsing -Method GET -Uri $url | ConvertFrom-Json + $filesChanged = @($response.files | ForEach-Object { $_.filename }) + if ($filesChanged.Count -lt 250) { + $foldersChanged = @($filesChanged | ForEach-Object { $_.Split('/')[0] } | Select-Object -Unique) + $projects = @($projects | Where-Object { $foldersChanged -contains $_ }) + Write-Host "Modified projects: $($projects -join ', ')" + } + } + } + if ($projects.Count -eq 1) { + $projectsJSon = "[$($projects | ConvertTo-Json -compress)]" + } + else { + $projectsJSon = $projects | ConvertTo-Json -compress + } + Write-Host "::set-output name=projects::$projectsJson" + Write-Host "::set-output name=projectCount::$($projects.Count)" + Write-Host "set-output name=projects::$projectsJson" + Write-Host "set-output name=projectCount::$($projects.Count)" + + Build: + needs: [ Analyze ] + runs-on: ${{ fromJson(needs.Analyze.outputs.githubRunner) }} + strategy: + matrix: + project: ${{ fromJson(needs.Analyze.outputs.projects) }} + fail-fast: false + name: Build ${{ matrix.project }} + outputs: + TestResultsArtifactsName: ${{ steps.calculateArtifactNames.outputs.TestResultsArtifactsName }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + project: ${{ matrix.project }} + + - name: Read secrets + uses: microsoft/AL-Go-Actions/ReadSecrets@main + env: + secrets: ${{ toJson(secrets) }} + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + settingsJson: ${{ env.Settings }} + secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' + + - name: Run pipeline + uses: microsoft/AL-Go-Actions/RunPipeline@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + settingsJson: ${{ env.Settings }} + SecretsJson: ${{ env.RepoSecrets }} + + - name: Calculate Artifact names + id: calculateArtifactNames + if: success() || failure() + run: | + $settings = '${{ env.Settings }}' | ConvertFrom-Json + $project = '${{ matrix.project }}' + if ($project -eq ".") { $project = $settings.RepoName } + $TestResultsArtifactsName = "$project-TestResults" + Write-Host "::set-output name=TestResultsArtifactsName::$TestResultsArtifactsName" + Add-Content -Path $env:GITHUB_ENV -Value "TestResultsArtifactsName=$TestResultsArtifactsName" + + - name: Publish artifacts - test results + uses: actions/upload-artifact@v2 + if: success() || failure() + with: + name: ${{ env.testResultsArtifactsName }} + path: '${{ matrix.project }}/TestResults.xml' + if-no-files-found: ignore + + - name: Cleanup + if: always() + uses: microsoft/AL-Go-Actions/PipelineCleanup@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + + PostProcess: + if: always() + runs-on: [ windows-latest ] + needs: [ Initialization, Analyze, Build ] + steps: + - name: Finalizing the workflow + id: PostProcess + uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main + with: + eventId: "DO0099" + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/NextMinor.yaml b/Templates/Per Tenant Extension/.github/workflows/NextMinor.yaml new file mode 100644 index 00000000..15a26f48 --- /dev/null +++ b/Templates/Per Tenant Extension/.github/workflows/NextMinor.yaml @@ -0,0 +1,157 @@ +name: Test Next Minor + +on: + workflow_dispatch: + +defaults: + run: + shell: PowerShell + +jobs: + Initialization: + runs-on: [ windows-latest ] + outputs: + telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} + steps: + - id: init + uses: microsoft/AL-Go-Actions/WorkflowInitialize@main + with: + eventId: "DO0100" + + Analyze: + runs-on: [ windows-latest ] + needs: [ Initialization ] + outputs: + projects: ${{ steps.Projects.outputs.projects }} + projectCount: ${{ steps.Projects.outputs.projectCount }} + githubRunner: ${{ steps.OutputSettings.outputs.githubRunner }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + get: githubRunner,alwaysBuildAllProjects + + - name: Output settings + id: OutputSettings + run: | + $gitHubRunner = "$env:githubRunner".Split(',') | ConvertTo-Json -compress + Write-Host "::set-output name=githubRunner::$githubRunner" + Write-Host "set-output name=githubRunner::$githubRunner" + + - name: Projects + id: Projects + run: | + if (Test-Path ".AL-Go" -PathType Container) { + $projects = @(".") + } + else { + $projects = @(Get-ChildItem -Path $ENV:GITHUB_WORKSPACE -Directory | Where-Object { Test-Path (Join-Path $_.FullName ".AL-Go") -PathType Container } | ForEach-Object { $_.Name }) + Write-Host "Projects: $($projects -join ', ')" + if (!($ENV:GITHUB_EVENT_NAME -eq "workflow_dispatch" -or "$ENV:alwaysBuildAllProjects" -eq "true")) { + $headers = @{ + "Authorization" = "token ${{ github.token }}" + "Accept" = "application/vnd.github.baptiste-preview+json" + } + if ($ENV:GITHUB_EVENT_NAME -eq "pull_request") { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.pull_request.base.sha }}...${{ github.sha }}" + } + else { + $url = "$($ENV:GITHUB_API_URL)/repos/$($ENV:GITHUB_REPOSITORY)/compare/${{ github.event.before }}...${{ github.event.after }}" + } + $response = Invoke-WebRequest -Headers $headers -UseBasicParsing -Method GET -Uri $url | ConvertFrom-Json + $filesChanged = @($response.files | ForEach-Object { $_.filename }) + if ($filesChanged.Count -lt 250) { + $foldersChanged = @($filesChanged | ForEach-Object { $_.Split('/')[0] } | Select-Object -Unique) + $projects = @($projects | Where-Object { $foldersChanged -contains $_ }) + Write-Host "Modified projects: $($projects -join ', ')" + } + } + } + if ($projects.Count -eq 1) { + $projectsJSon = "[$($projects | ConvertTo-Json -compress)]" + } + else { + $projectsJSon = $projects | ConvertTo-Json -compress + } + Write-Host "::set-output name=projects::$projectsJson" + Write-Host "::set-output name=projectCount::$($projects.Count)" + Write-Host "set-output name=projects::$projectsJson" + Write-Host "set-output name=projectCount::$($projects.Count)" + + Build: + needs: [ Analyze ] + runs-on: ${{ fromJson(needs.Analyze.outputs.githubRunner) }} + strategy: + matrix: + project: ${{ fromJson(needs.Analyze.outputs.projects) }} + fail-fast: false + name: Build ${{ matrix.project }} + outputs: + TestResultsArtifactsName: ${{ steps.calculateArtifactNames.outputs.TestResultsArtifactsName }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read settings + uses: microsoft/AL-Go-Actions/ReadSettings@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + project: ${{ matrix.project }} + + - name: Read secrets + uses: microsoft/AL-Go-Actions/ReadSecrets@main + env: + secrets: ${{ toJson(secrets) }} + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + settingsJson: ${{ env.Settings }} + secrets: 'licenseFileUrl,insiderSasToken,CodeSignCertificateUrl,CodeSignCertificatePassword,KeyVaultCertificateUrl,KeyVaultCertificatePassword,KeyVaultClientId' + + - name: Run pipeline + uses: microsoft/AL-Go-Actions/RunPipeline@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + settingsJson: ${{ env.Settings }} + SecretsJson: ${{ env.RepoSecrets }} + + - name: Calculate Artifact names + id: calculateArtifactNames + if: success() || failure() + run: | + $settings = '${{ env.Settings }}' | ConvertFrom-Json + $project = '${{ matrix.project }}' + if ($project -eq ".") { $project = $settings.RepoName } + $TestResultsArtifactsName = "$project-TestResults" + Write-Host "::set-output name=TestResultsArtifactsName::$TestResultsArtifactsName" + Add-Content -Path $env:GITHUB_ENV -Value "TestResultsArtifactsName=$TestResultsArtifactsName" + + - name: Publish artifacts - test results + uses: actions/upload-artifact@v2 + if: success() || failure() + with: + name: ${{ env.testResultsArtifactsName }} + path: '${{ matrix.project }}/TestResults.xml' + if-no-files-found: ignore + + - name: Cleanup + if: always() + uses: microsoft/AL-Go-Actions/PipelineCleanup@main + with: + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} + Project: ${{ matrix.project }} + + PostProcess: + if: always() + runs-on: [ windows-latest ] + needs: [ Initialization, Analyze, Build ] + steps: + - name: Finalizing the workflow + id: PostProcess + uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main + with: + eventId: "DO0100" + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/PublishToEnvironment.yaml b/Templates/Per Tenant Extension/.github/workflows/PublishToEnvironment.yaml index cd1feab9..27b4fb11 100644 --- a/Templates/Per Tenant Extension/.github/workflows/PublishToEnvironment.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/PublishToEnvironment.yaml @@ -17,19 +17,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0097" Analyze: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] outputs: environments: ${{ steps.Environments.outputs.environments }} environmentCount: ${{ steps.Environments.outputs.environmentCount }} @@ -112,21 +112,20 @@ jobs: env: authContext: '${{ steps.authContext.outputs.authContext }}' with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} type: 'Publish' projects: '${{ secrets.Projects }}' environmentName: ${{ matrix.environment }} artifacts: ${{ github.event.inputs.appVersion }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, Environments, Deploy ] + needs: [ Initialization, Analyze, Deploy ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0097" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} - + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/.github/workflows/UpdateGitHubGoSystemFiles.yaml b/Templates/Per Tenant Extension/.github/workflows/UpdateGitHubGoSystemFiles.yaml index d678ffc7..a751b126 100644 --- a/Templates/Per Tenant Extension/.github/workflows/UpdateGitHubGoSystemFiles.yaml +++ b/Templates/Per Tenant Extension/.github/workflows/UpdateGitHubGoSystemFiles.yaml @@ -17,19 +17,19 @@ defaults: shell: PowerShell jobs: - initialization: + Initialization: runs-on: [ windows-latest ] outputs: telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} steps: - id: init uses: microsoft/AL-Go-Actions/WorkflowInitialize@main - with: + with: eventId: "DO0098" - update: + Update: runs-on: [ windows-latest ] - needs: [ initialization ] + needs: [ Initialization ] steps: - name: Checkout @@ -38,7 +38,7 @@ jobs: - name: Read settings uses: microsoft/AL-Go-Actions/ReadSettings@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} get: KeyVaultName,GhTokenWorkflowSecretName,TemplateUrl - name: Read secrets @@ -46,7 +46,7 @@ jobs: env: secrets: ${{ toJson(secrets) }} with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} settingsJson: ${{ env.Settings }} secrets: 'ghTokenWorkflow=${{ env.GHTOKENWORKFLOWSECRETNAME }}' @@ -61,20 +61,20 @@ jobs: - name: Update AL-Go system files uses: microsoft/AL-Go-Actions/CheckForUpdates@main with: - parentTelemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} + parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} token: ${{ env.ghTokenWorkflow }} - update: Y + Update: Y templateUrl: ${{ env.TemplateUrl }} directCommit: ${{ github.event.inputs.directCommit }} - postProcess: + PostProcess: if: always() runs-on: [ windows-latest ] - needs: [ initialization, update ] + needs: [ Initialization, Update ] steps: - name: Finalizing the workflow - id: postProcess + id: PostProcess uses: microsoft/AL-Go-Actions/WorkflowPostProcess@main - with: + with: eventId: "DO0098" - telemetryScopeJson: ${{ needs.initialization.outputs.telemetryScopeJson }} \ No newline at end of file + telemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }} diff --git a/Templates/Per Tenant Extension/README.md b/Templates/Per Tenant Extension/README.md index c818f354..075daa3a 100644 --- a/Templates/Per Tenant Extension/README.md +++ b/Templates/Per Tenant Extension/README.md @@ -30,4 +30,4 @@ Finally, the latest release is also used as the "previous version" in CI pipelin ### Register customer environment The Register customer environment workflow will allow you to register a customer environment for automatic deployment of the apps in this repository. You have to specify tenant ID, name and environment name of the customer environment. For authentication, you need to create an AAD App and register this AAD App in the customer environment with permissions for automation and extension management. The Client Secret for this AAD App should be stored in a GitHub or KeyVault secret. The Client ID and the name of the secret needs to be specified when registering the customer environment. Finally, you can specify whether the environment is a sandbox environment and whether you want continuous deployment of the apps from the repository. ### Update AL-Go system files -Update AL-Go system files. This step requires you to create a GitHub secret called GHTOKENWORKFLOW with a personal access token, which has permissions to update workflow files in the repository. Go to https://github.com/settings/tokens, Generate a new token and check the workflow scope. +Update AL-Go system files. This step requires you to create a GitHub secret called GHTOKENWORKFLOW with a personal access token, which has permissions to update workflow files in the repository. Go to https://github.com/settings/tokens, generate a new token and check the workflow scope. diff --git a/e2eTests/Test-AL-Go.ps1 b/e2eTests/Test-AL-Go.ps1 index f9eecbaa..4e4ddca6 100644 --- a/e2eTests/Test-AL-Go.ps1 +++ b/e2eTests/Test-AL-Go.ps1 @@ -215,9 +215,9 @@ try { # Modify versioning strategy $projectSettingsFiles | ForEach-Object { - $repoSettings = Get-Content $_ -Encoding UTF8 | ConvertFrom-Json - $reposettings | Add-Member -NotePropertyName 'versioningStrategy' -NotePropertyValue 16 - $repoSettings | ConvertTo-Json | Set-Content $_ -Encoding UTF8 + $projectSettings = Get-Content $_ -Encoding UTF8 | ConvertFrom-Json + $projectsettings | Add-Member -NotePropertyName 'versioningStrategy' -NotePropertyValue 16 + $projectSettings | ConvertTo-Json | Set-Content $_ -Encoding UTF8 } Remove-Item -Path "$($project1Folder).AL-Go\*.ps1" -Force Remove-Item -Path ".github\workflows\CreateRelease.yaml" -Force @@ -229,12 +229,13 @@ try { $runs++ Pull -branch $branch if (Test-Path "$($project1Folder).AL-Go\*.ps1") { throw "Local PowerShell scripts in the .AL-Go folder should have been removed" } - if (Test-Path ".gitub\workflows\CreateRelease.yaml") { throw "CreateRelease.yaml should have been removed" } + if (Test-Path ".github\workflows\CreateRelease.yaml") { throw "CreateRelease.yaml should have been removed" } $run = Run-CICD -wait -branch $branch $runs++ Test-ArtifactsFromRun -runid $run.id -expectedNumberOfApps 3 -expectedNumberOfTestApps 2 -expectedNumberOfTests 2 -folder 'artifacts3' -repoVersion '3.0.' -appVersion '3.0' # Update AL-Go System Files + $repoSettings = Get-Content ".github\AL-Go-Settings.json" -Encoding UTF8 | ConvertFrom-Json SetRepositorySecret -name 'GHTOKENWORKFLOW' -value (ConvertTo-SecureString -String $token -AsPlainText -Force) Run-UpdateAlGoSystemFiles -templateUrl $repoSettings.templateUrl -wait -branch $branch | Out-Null $runs++