├── .devcontainer └── devcontainer.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ └── config.yml ├── dependabot.yml └── workflows │ ├── CI.yaml │ ├── CleanupTempRepos.yaml │ ├── Deploy.yaml │ ├── E2E.yaml │ ├── StaleIssues.yml │ ├── powershell.yaml │ ├── pre-commit.yml │ └── scorecard-analysis.yml ├── .gitignore ├── .pre-commit-config.yaml ├── Actions ├── AL-Go-Helper.ps1 ├── AL-Go-TestRepoHelper.ps1 ├── AddExistingApp │ ├── AddExistingApp.ps1 │ ├── README.md │ └── action.yaml ├── AnalyzeTests │ ├── AnalyzeTests.ps1 │ ├── README.md │ ├── TestResultAnalyzer.ps1 │ └── action.yaml ├── BuildPowerPlatform │ ├── BuildPowerPlatform.ps1 │ ├── README.md │ └── action.yaml ├── BuildReferenceDocumentation │ ├── BuildReferenceDocumentation.HelperFunctions.ps1 │ ├── BuildReferenceDocumentation.ps1 │ ├── README.md │ └── action.yaml ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CalculateArtifactNames │ ├── CalculateArtifactNames.ps1 │ ├── README.md │ └── action.yaml ├── CheckForUpdates │ ├── CheckForUpdates.HelperFunctions.ps1 │ ├── CheckForUpdates.ps1 │ ├── README.md │ ├── action.yaml │ └── yamlclass.ps1 ├── CreateApp │ ├── AppHelper.psm1 │ ├── AppTemplate │ │ ├── .vscode │ │ │ └── launch.json │ │ ├── HelloWorld.Test.al │ │ ├── HelloWorld.al │ │ ├── app.json │ │ └── bcptSuite.json │ ├── CreateApp.ps1 │ ├── README.md │ └── action.yaml ├── CreateDevelopmentEnvironment │ ├── CreateDevelopmentEnvironment.ps1 │ ├── README.md │ └── action.yaml ├── CreateReleaseNotes │ ├── CreateReleaseNotes.ps1 │ ├── README.md │ └── action.yaml ├── Deliver │ ├── Deliver.ps1 │ ├── README.md │ └── action.yaml ├── Deploy │ ├── Deploy.ps1 │ ├── Deploy.psm1 │ ├── README.md │ └── action.yaml ├── DeployPowerPlatform │ ├── DeterminePowerPlatformSolutionFolder.ps1 │ ├── README.md │ └── action.yaml ├── DetermineArtifactUrl │ ├── DetermineArtifactUrl.ps1 │ ├── README.md │ └── action.yaml ├── DetermineArtifactsForRelease │ ├── DetermineArtifactsForRelease.ps1 │ ├── README.md │ └── action.yaml ├── DetermineBuildProject │ ├── DetermineBuildProject.ps1 │ ├── README.md │ └── action.yaml ├── DetermineDeliveryTargets │ ├── DetermineDeliveryTargets.ps1 │ ├── README.md │ └── action.yaml ├── DetermineDeploymentEnvironments │ ├── DetermineDeploymentEnvironments.ps1 │ ├── README.md │ └── action.yaml ├── DetermineProjectsToBuild │ ├── DetermineProjectsToBuild.Action.ps1 │ ├── DetermineProjectsToBuild.psm1 │ ├── README.md │ └── action.yaml ├── DownloadProjectDependencies │ ├── DownloadProjectDependencies.Action.ps1 │ ├── README.md │ └── action.yaml ├── DumpWorkflowInfo │ ├── DumpWorkflowInfo.ps1 │ ├── README.md │ └── action.yaml ├── GetArtifactsForDeployment │ ├── GetArtifactsForDeployment.ps1 │ ├── GetArtifactsForDeployment.psm1 │ ├── README.md │ └── action.yaml ├── GetWorkflowMultiRunBranches │ ├── GetWorkflowMultiRunBranches.ps1 │ ├── README.md │ └── action.yaml ├── Github-Helper.psm1 ├── IncrementVersionNumber │ ├── IncrementVersionNumber.ps1 │ ├── IncrementVersionNumber.psm1 │ ├── README.md │ └── action.yaml ├── Invoke-AlGoAction.ps1 ├── LICENSE ├── MarkDownHelper.psm1 ├── Packages.json ├── PipelineCleanup │ ├── PipelineCleanup.ps1 │ ├── README.md │ └── action.yaml ├── PullPowerPlatformChanges │ ├── GitCloneReponsitory.ps1 │ ├── GitCommitChanges.ps1 │ ├── README.md │ └── action.yaml ├── PullRequestStatusCheck │ ├── PullRequestStatusCheck.ps1 │ ├── README.md │ └── action.yaml ├── README.md ├── ReadPowerPlatformSettings │ ├── README.md │ ├── ReadPowerPlatformSettings.ps1 │ └── action.yaml ├── ReadSecrets │ ├── README.md │ ├── ReadSecrets.ps1 │ ├── ReadSecretsHelper.psm1 │ └── action.yaml ├── ReadSettings │ ├── README.md │ ├── ReadSettings.ps1 │ └── action.yaml ├── RunPSScriptAnalyzer │ ├── README.md │ ├── RunPSScriptAnalyzer.ps1 │ └── action.yml ├── RunPipeline │ ├── CheckForWarningsUtils.psm1 │ ├── README.md │ ├── RunPipeline.ps1 │ └── action.yaml ├── SECURITY.md ├── SUPPORT.md ├── SetActionsRepoAndRef.ps1 ├── Sign │ ├── README.md │ ├── Sign.ps1 │ ├── Sign.psm1 │ └── action.yaml ├── TelemetryHelper.psm1 ├── Troubleshooting │ ├── README.md │ ├── Troubleshoot.Secrets.ps1 │ ├── Troubleshooting.ps1 │ └── action.yaml ├── ValidateWorkflowInput │ ├── README.md │ ├── Validate-createrelease.ps1 │ ├── Validate-incrementversionnumber.ps1 │ ├── ValidateWorkflowInput.ps1 │ ├── ValidateWorkflowInput.psm1 │ └── action.yaml ├── VerifyPRChanges │ ├── README.md │ ├── VerifyPRChanges.ps1 │ └── action.yaml ├── WorkflowInitialize │ ├── README.md │ ├── WorkflowInitialize.ps1 │ └── action.yaml ├── WorkflowPostProcess │ ├── README.md │ ├── WorkflowPostProcess.ps1 │ └── action.yaml └── settings.schema.json ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── DEPRECATIONS.md ├── Internal ├── Deploy.ps1 ├── Overrides │ ├── 1st party apps │ │ └── NewBcContainer.ps1 │ └── System Application │ │ └── NewBcContainer.ps1 └── Scripts │ ├── GetOwnerForE2ETests.ps1 │ └── RemoveTempRepos.ps1 ├── LICENSE ├── README.md ├── RELEASENOTES.md ├── SECURITY.md ├── SUPPORT.md ├── Scenarios ├── AddAPerformanceTestApp.md ├── AddATestApp.md ├── AddPowerPlatformProject.md ├── AppDependencies.md ├── Codesigning.md ├── Contribute.md ├── CreateOnlineDevEnv.md ├── CreateOnlineDevEnv2.md ├── CreateRelease.md ├── EnableKeyVaultForAppSourceApp.md ├── EnablingTelemetry.md ├── GetStarted.md ├── GhTokenWorkflow.md ├── MigrateFromAzureDevOpsWithHistory.md ├── MigrateFromAzureDevOpsWithoutHistory.md ├── PublishToAppSource.md ├── RegisterProductionEnvironment.md ├── RegisterSandboxEnvironment.md ├── SelfHostedGitHubRunner.md ├── SetupCiCdForExistingAppSourceApp.md ├── SetupCiCdForExistingPTE.md ├── SetupPowerPlatform.md ├── SetupServicePrincipalForPowerPlatform.md ├── TryPowerPlatformSamples.md ├── UpdateAlGoSystemFiles.md ├── UseAzureKeyVault.md ├── images │ └── branchingstrategy.png ├── resources │ └── telemetrydashboard.json ├── secrets.md └── settings.md ├── Templates ├── AppSource App │ ├── .AL-Go │ │ ├── cloudDevEnv.ps1 │ │ ├── localDevEnv.ps1 │ │ └── settings.json │ ├── .github │ │ ├── AL-Go-Settings.json │ │ ├── Test Current.settings.json │ │ ├── Test Next Major.settings.json │ │ ├── Test Next Minor.settings.json │ │ └── workflows │ │ │ ├── AddExistingAppOrTestApp.yaml │ │ │ ├── CICD.yaml │ │ │ ├── CreateApp.yaml │ │ │ ├── CreateOnlineDevelopmentEnvironment.yaml │ │ │ ├── CreatePerformanceTestApp.yaml │ │ │ ├── CreateRelease.yaml │ │ │ ├── CreateTestApp.yaml │ │ │ ├── Current.yaml │ │ │ ├── DeployReferenceDocumentation.yaml │ │ │ ├── IncrementVersionNumber.yaml │ │ │ ├── NextMajor.yaml │ │ │ ├── NextMinor.yaml │ │ │ ├── PublishToAppSource.yaml │ │ │ ├── PublishToEnvironment.yaml │ │ │ ├── PullRequestHandler.yaml │ │ │ ├── Troubleshooting.yaml │ │ │ ├── UpdateGitHubGoSystemFiles.yaml │ │ │ └── _BuildALGoProject.yaml │ ├── .gitignore │ ├── CODEOWNERS │ ├── README.md │ ├── SECURITY.md │ ├── SUPPORT.md │ └── al.code-workspace ├── Per Tenant Extension │ ├── .AL-Go │ │ ├── cloudDevEnv.ps1 │ │ ├── localDevEnv.ps1 │ │ └── settings.json │ ├── .github │ │ ├── AL-Go-Settings.json │ │ ├── Test Current.settings.json │ │ ├── Test Next Major.settings.json │ │ ├── Test Next Minor.settings.json │ │ └── workflows │ │ │ ├── AddExistingAppOrTestApp.yaml │ │ │ ├── CICD.yaml │ │ │ ├── CreateApp.yaml │ │ │ ├── CreateOnlineDevelopmentEnvironment.yaml │ │ │ ├── CreatePerformanceTestApp.yaml │ │ │ ├── CreateRelease.yaml │ │ │ ├── CreateTestApp.yaml │ │ │ ├── Current.yaml │ │ │ ├── DeployReferenceDocumentation.yaml │ │ │ ├── IncrementVersionNumber.yaml │ │ │ ├── NextMajor.yaml │ │ │ ├── NextMinor.yaml │ │ │ ├── PublishToEnvironment.yaml │ │ │ ├── PullPowerPlatformChanges.yaml │ │ │ ├── PullRequestHandler.yaml │ │ │ ├── PushPowerPlatformChanges.yaml │ │ │ ├── Troubleshooting.yaml │ │ │ ├── UpdateGitHubGoSystemFiles.yaml │ │ │ ├── _BuildALGoProject.yaml │ │ │ └── _BuildPowerPlatformSolution.yaml │ ├── .gitignore │ ├── CODEOWNERS │ ├── README.md │ ├── SECURITY.md │ ├── SUPPORT.md │ └── al.code-workspace └── README.md ├── Tests ├── AL-Go-Helper.Test.ps1 ├── AddExistingApp.Action.Test.ps1 ├── AnalyzeTests.Test.ps1 ├── AppHelper.Test.ps1 ├── BuildPowerPlatform.Action.Test.ps1 ├── BuildReferenceDocumentation.Action.Test.ps1 ├── CalculateArtifactNames.Test.ps1 ├── CheckForUpdates.Action.Test.ps1 ├── CreateApp.Action.Test.ps1 ├── CreateDevelopmentEnvironment.Action.Test.ps1 ├── CreateReleaseNotes.Test.ps1 ├── Deliver.Action.Test.ps1 ├── Deploy.Action.Test.ps1 ├── DetermineArtifactUrl.Test.ps1 ├── DetermineArtifactsForRelease.Test.ps1 ├── DetermineDeliveryTargets.Test.ps1 ├── DetermineDeploymentEnvironments.Test.ps1 ├── DetermineProjectsToBuild.Test.ps1 ├── GetWorkflowMultiRunBranches.Test.ps1 ├── GitHub-Helper.Test.ps1 ├── IncrementVersionNumber.Action.Test.ps1 ├── MarkdownLinks │ └── AkaMSLinks.Test.ps1 ├── PipelineCleanup.Action.Test.ps1 ├── PullRequestStatusCheck.Test.ps1 ├── ReadPowerPlatformSettings.Action.Test.ps1 ├── ReadSecrets.Action.Test.ps1 ├── ReadSettings.Action.Test.ps1 ├── ResolveProjectFolders.Test.ps1 ├── RunPipeline.Action.Test.ps1 ├── Sign.Test.ps1 ├── TestActionsHelper.psm1 ├── Troubleshooting.Test.ps1 ├── ValidateWorkflowInput.Test.ps1 ├── VerifyPRChanges.Action.Test.ps1 ├── WorkflowInitialize.Test.ps1 ├── WorkflowPostProcess.Test.ps1 ├── WorkflowSanitation │ ├── WorkflowFileContent.Test.ps1 │ ├── WorkflowFileExtensions.Test.ps1 │ └── WorkflowReferences.Test.ps1 ├── YamlSnippet.txt ├── _TestData-PowerPlatform │ ├── FlowOnlySolution │ │ ├── Workflows │ │ │ └── Trigger-ABA81736-12D9-ED11-A7C7-000D3A991110.json │ │ └── other │ │ │ └── Solution.xml │ ├── PowerAppOnlySolution │ │ ├── CanvasApps │ │ │ └── src │ │ │ │ └── TestApp │ │ │ │ ├── Connections │ │ │ │ └── Connections.json │ │ │ │ └── DataSources │ │ │ │ ├── customers %28v2.0%29.json │ │ │ │ ├── salesOrderLines %28v2.0%29.json │ │ │ │ └── salesOrders %28v2.0%29.json │ │ └── other │ │ │ └── Solution.xml │ └── StandardSolution │ │ ├── CanvasApps │ │ └── src │ │ │ └── TestApp │ │ │ ├── Connections │ │ │ └── Connections.json │ │ │ └── DataSources │ │ │ ├── customers %28v2.0%29.json │ │ │ ├── salesOrderLines %28v2.0%29.json │ │ │ └── salesOrders %28v2.0%29.json │ │ ├── Workflows │ │ └── TestWorkflow-ABA81736-12D9-ED11-A7C7-000D3A991110.json │ │ └── other │ │ └── Solution.xml └── runtests.ps1 ├── Workshop ├── AddAnApp.md ├── AutomatedTests.md ├── ContinuousDelivery.md ├── ContinuousDeployment.md ├── Dependencies1.md ├── Dependencies2.md ├── Dependencies3.md ├── DevelopmentEnvironments.md ├── GetStarted.md ├── Index.md ├── Introduction.md ├── KeepUpToDate.md ├── PerformanceTesting.md ├── Prerequisites.md ├── Projects.md ├── PublishToProduction.md ├── ReferenceDoc.md ├── Releasing.md ├── ScheduledTestRuns.md ├── TheDevelopmentProcess.md └── Versioning.md ├── _config.yml └── e2eTests ├── SetupRepositories.ps1 ├── Test-AL-Go-Upgrade.ps1 ├── Test-AL-Go.ps1 ├── Test-Functions.ps1 ├── Workflows ├── RunAddExistingAppOrTestApp.ps1 ├── RunCICD.ps1 ├── RunCreateApp.ps1 ├── RunCreateOnlineDevelopmentEnvironment.ps1 ├── RunCreateRelease.ps1 ├── RunCreateTestApp.ps1 ├── RunDeployReferenceDocumentation.ps1 ├── RunIncrementVersionNumber.ps1 ├── RunPublishToEnvironment.ps1 ├── RunTestCurrent.ps1 ├── RunTestNextMajor.ps1 ├── RunTestNextMinor.ps1 └── RunUpdateAlGoSystemFiles.ps1 ├── appsourceapp ├── My App.Test │ ├── .vscode │ │ └── launch.json │ ├── HelloWorld.Test.al │ └── app.json └── My App │ ├── .vscode │ └── launch.json │ ├── HelloWorld.al │ ├── app.json │ └── helloworld256x240.png ├── e2eTestHelper.psm1 ├── orgmap.json ├── pte ├── My App.Test │ ├── .vscode │ │ └── launch.json │ ├── HelloWorld.Test.al │ └── app.json └── My App │ ├── .vscode │ └── launch.json │ ├── HelloWorld.al │ └── app.json └── scenarios ├── BCApps └── runtest.ps1 ├── BuildModes └── runtest.ps1 ├── FederatedCredentials └── runtest.ps1 ├── GitHubPackages └── runtest.ps1 ├── IncludeDependencies └── runtest.ps1 ├── IncrementalBuilds └── runtest.ps1 ├── PowerPlatform └── runtest.ps1 ├── ReferenceDocumentation └── runtest.ps1 ├── ReleaseBranches └── runtest.ps1 ├── SpecialCharacters └── runtest.ps1 └── UseProjectDependencies └── runtest.ps1 /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/devcontainers/universal:latest", 3 | "tasks": { 4 | "build": "", 5 | "test": "pwsh -File Tests/runtests.ps1", 6 | "run": "" 7 | }, 8 | "features": { 9 | "ghcr.io/devcontainers/features/powershell:1": { 10 | "modules": "BcContainerHelper,Pester" 11 | }, 12 | "ghcr.io/devcontainers/features/github-cli:1": {} 13 | }, 14 | "postCreateCommand": "pip install pre-commit && pre-commit install --install-hooks --overwrite", 15 | "customizations": { 16 | "vscode": { 17 | "extensions": [ 18 | "GitHub.copilot", 19 | "GitHub.copilot-chat", 20 | "GitHub.vscode-github-actions", 21 | "GitHub.vscode-pull-request-github", 22 | "ms-vscode.powershell" 23 | ], 24 | "settings": { 25 | "terminal.integrated.defaultProfile.linux": "pwsh" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Report a bug 2 | description: Report a bug in AL-Go for GitHub 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report! 10 | 11 | Before you create a new issue, please check the following: 12 | 🔎 Search existing issues to avoid creating duplicates. 13 | 14 | - type: input 15 | id: algoversion 16 | attributes: 17 | label: AL-Go version 18 | description: The version of AL-Go you are using 19 | placeholder: For example 5.1 or preview 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: describe-the-issue 24 | attributes: 25 | label: Describe the issue 26 | description: A clear and concise description of what the issue is 27 | placeholder: Describe the issue 28 | validations: 29 | required: true 30 | - type: textarea 31 | id: expected-behavior 32 | attributes: 33 | label: Expected behavior 34 | description: Describe what behavior you expected 35 | placeholder: Expected behavior 36 | validations: 37 | required: true 38 | - type: textarea 39 | id: steps-to-reproduce 40 | attributes: 41 | label: Steps to reproduce 42 | description: List of steps to reproduce 43 | placeholder: Steps to reproduce 44 | validations: 45 | required: true 46 | - type: textarea 47 | id: additional-context 48 | attributes: 49 | label: Additional context (logs, screenshots, etc.) 50 | description: To help us understand the issue better please paste some logs in the box below. Without logs, it will be harder to understand the issue. Make sure you don't share any sensitive information such as API keys, passwords, etc. 51 | placeholder: Screenshots, log output, etc. 52 | validations: 53 | required: false 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature request 4 | url: https://github.com/microsoft/AL-Go/discussions/new?category=ideas 5 | about: Are you missing a feature in AL-Go for GitHub? Please share your ideas with us in the discussion forum. 6 | - name: Ask a question 7 | url: https://github.com/microsoft/AL-Go/discussions/new?category=q-a 8 | about: Do you have a question about AL-Go for GitHub? Please ask us in the discussion forum. 9 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Configuration options at https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: github-actions 6 | directories: 7 | - ".github/workflows/" 8 | - "/Templates/**/.github/workflows/" 9 | - "/Actions/**/" 10 | groups: 11 | External-Dependencies: 12 | applies-to: version-updates 13 | dependency-type: "production" 14 | ignore: 15 | - dependency-name: "microsoft/AL-Go-Actions/*" 16 | schedule: 17 | interval: weekly 18 | -------------------------------------------------------------------------------- /.github/workflows/CI.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | workflow_dispatch: 9 | 10 | defaults: 11 | run: 12 | shell: pwsh 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | Test: 19 | runs-on: [ ubuntu-latest ] 20 | steps: 21 | - name: Harden Runner 22 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 23 | with: 24 | egress-policy: audit 25 | 26 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | 28 | - name: Run AL-Go Actions Tests 29 | run: | 30 | . (Join-Path "." "Tests/runtests.ps1") -Path "Tests" 31 | 32 | - name: Test AL-Go Workflows 33 | if: github.repository_owner == 'microsoft' 34 | run: | 35 | . (Join-Path "." "Tests/runtests.ps1") -Path "Tests/WorkflowSanitation" 36 | 37 | - name: Test aka.ms links in markdown files 38 | if: github.repository_owner == 'microsoft' 39 | run: | 40 | . (Join-Path "." "Tests/runtests.ps1") -Path "Tests/MarkdownLinks" 41 | -------------------------------------------------------------------------------- /.github/workflows/StaleIssues.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues 2 | 3 | on: 4 | schedule: 5 | - cron: '44 5 * * 2' # Tuesday, 5:44 6 | workflow_dispatch: 7 | 8 | jobs: 9 | stale: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | 14 | steps: 15 | - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 16 | with: 17 | stale-issue-label: 'stale' 18 | days-before-issue-stale: 180 19 | days-before-issue-close: 14 20 | close-issue-message: 'There has been no recent activity on this issue. Please re-open or create a new issue, if needed.' 21 | -------------------------------------------------------------------------------- /.github/workflows/powershell.yaml: -------------------------------------------------------------------------------- 1 | # https://github.com/microsoft/action-psscriptanalyzer 2 | # For more information on PSScriptAnalyzer in general, see 3 | # https://github.com/PowerShell/PSScriptAnalyzer 4 | 5 | name: PSScriptAnalyzer 6 | 7 | on: 8 | push: 9 | branches: [ "main" ] 10 | pull_request: 11 | branches: [ "main" ] 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | build: 18 | name: PSScriptAnalyzer 19 | runs-on: ubuntu-latest 20 | permissions: 21 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results 22 | steps: 23 | - name: Harden Runner 24 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 25 | with: 26 | egress-policy: audit 27 | 28 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | 30 | - name: Run PSScriptAnalyzer 31 | uses: ./Actions/RunPSScriptAnalyzer 32 | with: 33 | path: .\ 34 | recurse: true 35 | excludeRule: 'PSAvoidUsingInvokeExpression, PSUseShouldProcessForStateChangingFunctions, PSAvoidUsingWriteHost, PSAvoidUsingCmdletAliases, PSUseSingularNouns' 36 | output: results.sarif 37 | 38 | # Upload the SARIF file generated in the previous step 39 | - name: Upload SARIF results file 40 | uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 41 | with: 42 | sarif_file: results.sarif 43 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit.yml: -------------------------------------------------------------------------------- 1 | name: pre-commit 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | pre-commit: 14 | runs-on: windows-latest 15 | steps: 16 | - name: Harden Runner 17 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 18 | with: 19 | egress-policy: audit 20 | 21 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 22 | - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 23 | - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 24 | with: 25 | extra_args: --all-files 26 | -------------------------------------------------------------------------------- /.github/workflows/scorecard-analysis.yml: -------------------------------------------------------------------------------- 1 | name: Scorecard Analysis 2 | on: 3 | branch_protection_rule: 4 | schedule: 5 | - cron: "0 8 * * 4" # Weekly on Thursday at 08:00 UTC 6 | push: 7 | branches: ["main"] 8 | 9 | permissions: read-all 10 | 11 | jobs: 12 | analysis: 13 | name: Scorecard analysis 14 | runs-on: ubuntu-latest 15 | permissions: 16 | security-events: write # Needed to upload the results to code-scanning dashboard. 17 | id-token: write # Needed to publish results and get a badge (see publish_results below). 18 | 19 | steps: 20 | - name: Harden Runner 21 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 22 | with: 23 | egress-policy: audit 24 | 25 | - name: "Checkout code" 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | with: 28 | persist-credentials: false 29 | 30 | - name: "Run analysis" 31 | uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 32 | with: 33 | results_file: results.sarif 34 | results_format: sarif 35 | publish_results: true 36 | 37 | # Upload the results to GitHub's code scanning dashboard. 38 | - name: "Upload to code-scanning" 39 | uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 40 | with: 41 | sarif_file: results.sarif 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | ~$* 3 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | 4 | repos: 5 | - repo: https://github.com/executablebooks/mdformat 6 | rev: 0.7.21 7 | hooks: 8 | - id: mdformat 9 | args: [--end-of-line=keep] 10 | 11 | - repo: https://github.com/pre-commit/pre-commit-hooks 12 | rev: v5.0.0 13 | hooks: 14 | - id: check-added-large-files 15 | - id: check-case-conflict 16 | - id: check-json 17 | - id: check-xml 18 | - id: check-yaml 19 | - id: check-merge-conflict 20 | - id: detect-private-key 21 | - id: end-of-file-fixer 22 | - id: trailing-whitespace 23 | - id: mixed-line-ending 24 | - id: sort-simple-yaml 25 | 26 | - repo: https://github.com/gitleaks/gitleaks 27 | rev: v8.16.3 28 | hooks: 29 | - id: gitleaks 30 | -------------------------------------------------------------------------------- /Actions/AddExistingApp/README.md: -------------------------------------------------------------------------------- 1 | # Add existing app 2 | 3 | Add an existing app to an AL-Go for GitHub repository 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | actor | | The GitHub actor running the action | github.actor | 17 | | token | | The GitHub token running the action | github.token | 18 | | project | | Project name if the repository is setup for multiple projects | . | 19 | | url | Yes | Direct Download Url of .app or .zip file to add to the repository | | 20 | | updateBranch | | Which branch should the app be added to | github.ref_name | 21 | | directCommit | | true if the action should create a direct commit against the branch or false to create a Pull Request | false | 22 | 23 | ## OUTPUT 24 | 25 | none 26 | -------------------------------------------------------------------------------- /Actions/AddExistingApp/action.yaml: -------------------------------------------------------------------------------- 1 | name: Add Existing App 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | actor: 9 | description: The GitHub actor running the action 10 | required: false 11 | default: ${{ github.actor }} 12 | token: 13 | description: The GitHub token running the action 14 | required: false 15 | default: ${{ github.token }} 16 | project: 17 | description: Project name if the repository is setup for multiple projects 18 | required: false 19 | default: '.' 20 | url: 21 | description: Direct Download Url of .app or .zip file 22 | required: true 23 | updateBranch: 24 | description: Set the branch to update 25 | required: false 26 | default: ${{ github.ref_name }} 27 | directCommit: 28 | description: Direct Commit? 29 | required: false 30 | default: 'false' 31 | runs: 32 | using: composite 33 | steps: 34 | - name: run 35 | shell: ${{ inputs.shell }} 36 | env: 37 | _actor: ${{ inputs.actor }} 38 | _token: ${{ inputs.token }} 39 | _project: ${{ inputs.project }} 40 | _url: ${{ inputs.url }} 41 | _updateBranch: ${{ inputs.updateBranch }} 42 | _directCommit: ${{ inputs.directCommit }} 43 | run: | 44 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "AddExistingApp" -Action { 45 | ${{ github.action_path }}/AddExistingApp.ps1 -actor $ENV:_actor -token $ENV:_token -project $ENV:_project -url $ENV:_url -updateBranch $ENV:_updateBranch -directCommit ($ENV:_directCommit -eq 'true') 46 | } 47 | branding: 48 | icon: terminal 49 | color: blue 50 | -------------------------------------------------------------------------------- /Actions/AnalyzeTests/README.md: -------------------------------------------------------------------------------- 1 | # Analyze Tests 2 | 3 | Analyze results of tests from the RunPipeline action 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | project | Yes | Name of project to analyze or . if the repository is setup for single project | | 17 | | testType | Yes | Which type of tests to analyze. Should be one of ('normal', 'bcpt', 'pageScripting') | | 18 | 19 | ## OUTPUT 20 | 21 | ### ENV variables 22 | 23 | none 24 | 25 | ### OUTPUT variables 26 | 27 | none 28 | 29 | ### SUMMARY 30 | 31 | This function will set the test result markdown in the GITHUB_STEP_SUMMARY section 32 | -------------------------------------------------------------------------------- /Actions/AnalyzeTests/action.yaml: -------------------------------------------------------------------------------- 1 | name: Analyze Tests 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | project: 9 | description: Project to analyze 10 | required: false 11 | default: '.' 12 | testType: 13 | description: Tests to analyze 14 | required: true 15 | runs: 16 | using: composite 17 | steps: 18 | - name: run 19 | shell: ${{ inputs.shell }} 20 | env: 21 | _project: ${{ inputs.project }} 22 | _testType: ${{ inputs.testType }} 23 | run: | 24 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "AnalyzeTests" -Action { 25 | ${{ github.action_path }}/AnalyzeTests.ps1 -project $ENV:_project -testType $ENV:_testType 26 | } 27 | branding: 28 | icon: terminal 29 | color: blue 30 | -------------------------------------------------------------------------------- /Actions/BuildPowerPlatform/README.md: -------------------------------------------------------------------------------- 1 | # Build Power Platform 2 | 3 | Build the Power Platform solution 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | solutionFolder | Yes | The Power Platform solution path | | 17 | | outputFolder | Yes | Output folder where the zip file will be placed | | 18 | | outputFileName | Yes | The name of the output zip file | | 19 | | companyId | | The Business Central company ID | | 20 | | environmentName | | The Business Central environment name | | 21 | | appBuild | | The app build number | | 22 | | appRevision | | The app revision number | | 23 | 24 | ## OUTPUT 25 | 26 | none 27 | -------------------------------------------------------------------------------- /Actions/BuildReferenceDocumentation/README.md: -------------------------------------------------------------------------------- 1 | # BuildReferenceDocumentation 2 | 3 | Build documentation using [ALDoc](https://go.microsoft.com/fwlink/?linkid=2247728) and [DocFx](https://dotnet.github.io/docfx) 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | token | | The GitHub token running the action | github.token | 19 | | artifacts | Yes | The artifacts to build documentation for or a folder in which the artifacts have been downloaded | | 20 | 21 | ## OUTPUT 22 | 23 | none 24 | -------------------------------------------------------------------------------- /Actions/BuildReferenceDocumentation/action.yaml: -------------------------------------------------------------------------------- 1 | name: Build Reference Documentation 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | artifacts: 13 | description: The artifacts to build documentation for or a folder in which the artifacts have been downloaded 14 | required: true 15 | runs: 16 | using: composite 17 | steps: 18 | - name: run 19 | shell: ${{ inputs.shell }} 20 | env: 21 | _token: ${{ inputs.token }} 22 | _artifacts: ${{ inputs.artifacts }} 23 | run: | 24 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "BuildReferenceDocumentation" -Action { 25 | ${{ github.action_path }}/BuildReferenceDocumentation.ps1 -token $ENV:_token -artifacts $ENV:_artifacts 26 | } 27 | branding: 28 | icon: terminal 29 | color: blue 30 | -------------------------------------------------------------------------------- /Actions/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/dynamics-smb-engineering-systems 2 | -------------------------------------------------------------------------------- /Actions/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /Actions/CalculateArtifactNames/CalculateArtifactNames.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "Name of the built project", Mandatory = $true)] 3 | [string] $project, 4 | [Parameter(HelpMessage = "Build mode used when building the artifacts", Mandatory = $true)] 5 | [string] $buildMode, 6 | [Parameter(HelpMessage = "Suffix to add to the artifacts names", Mandatory = $false)] 7 | [string] $suffix 8 | ) 9 | 10 | function Set-OutputVariable([string] $name, [string] $value) { 11 | Write-Host "Assigning $value to $name" 12 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "$name=$value" 13 | } 14 | 15 | $settings = $env:Settings | ConvertFrom-Json 16 | 17 | if ($project -eq ".") { 18 | $project = $settings.repoName 19 | } 20 | 21 | $branchName = $ENV:GITHUB_HEAD_REF 22 | # $ENV:GITHUB_HEAD_REF is specified only for pull requests, so if it is not specified, use GITHUB_REF_NAME 23 | if (!$branchName) { 24 | $branchName = $ENV:GITHUB_REF_NAME 25 | } 26 | 27 | $branchName = $branchName.Replace('\', '_').Replace('/', '_') 28 | $projectName = $project.Replace('\', '_').Replace('/', '_') 29 | 30 | # If the buildmode is default, then we don't want to add it to the artifact name 31 | if ($buildMode -eq 'Default') { 32 | $buildMode = '' 33 | } 34 | Set-OutputVariable -name "BuildMode" -value $buildMode 35 | 36 | if ($suffix) { 37 | # Add the date to the suffix 38 | $suffix = "$suffix-$([DateTime]::UtcNow.ToString('yyyyMMdd'))" 39 | } 40 | else { 41 | $repoVersion = [System.Version]$settings.repoVersion 42 | $appBuild = $settings.appBuild 43 | if ($appBuild -eq -1) { 44 | $appBuild = $repoVersion.Build 45 | if ($repoVersion.Build -eq -1) { 46 | $appBuild = 0 47 | } 48 | } 49 | $suffix = "$($repoVersion.Major).$($repoVersion.Minor).$($appBuild).$($settings.appRevision)" 50 | } 51 | 52 | 'Apps', 'Dependencies', 'TestApps', 'TestResults', 'BcptTestResults', 'PageScriptingTestResults', 'PageScriptingTestResultDetails', 'BuildOutput', 'ContainerEventLog', 'PowerPlatformSolution' | ForEach-Object { 53 | $name = "$($_)ArtifactsName" 54 | $value = "$($projectName)-$($branchName)-$buildMode$_-$suffix" 55 | Set-OutputVariable -name $name -value $value 56 | } 57 | -------------------------------------------------------------------------------- /Actions/CalculateArtifactNames/README.md: -------------------------------------------------------------------------------- 1 | # Calculate Artifact Names 2 | 3 | Calculate Artifact Names for AL-Go workflows 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | project | Yes | Name of the built project or . if the repository is setup for single project | | 19 | | buildMode | Yes |Build mode used when building the artifacts | | 20 | | suffix | | A suffix to add to artifacts names. **Note:** if a suffix is specified, the current date will be added extra | Build version | 21 | 22 | ## OUTPUT 23 | 24 | ### ENV variables 25 | 26 | none 27 | 28 | ### OUTPUT variables 29 | 30 | | Name | Description | 31 | | :-- | :-- | 32 | | AppsArtifactsName | Artifacts name for Apps | 33 | | PowerPlatformSolutionArtifactsName | Artifacts name for PowerPlatform Solution | 34 | | DependenciesArtifactsName | Artifacts name for Dependencies | 35 | | TestAppsArtifactsName | Artifacts name for TestApps | 36 | | TestResultsArtifactsName | Artifacts name for TestResults | 37 | | BcptTestResultsArtifactsName | Artifacts name for BcptTestResults | 38 | | PageScriptingTestResultsArtifactsName | Artifacts name for PageScriptingTestResults | 39 | | PageScriptingTestResultDetailsArtifactsName | Artifacts name for PageScriptingTestResultDetails | 40 | | BuildOutputArtifactsName | Artifacts name for BuildOutput | 41 | | ContainerEventLogArtifactsName | Artifacts name for ContainerEventLog | 42 | | BuildMode | Build mode used when building the artifacts | 43 | -------------------------------------------------------------------------------- /Actions/CheckForUpdates/README.md: -------------------------------------------------------------------------------- 1 | # Check for updates 2 | 3 | Check for updates to AL-Go system files and perform the update if requested 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | actor | | The GitHub actor running the action | github.actor | 17 | | token | | The GitHub token running the action | github.token | 18 | | templateUrl | | URL of the template repository (default is the template repository used to create the repository) | default | 19 | | downloadLatest | Yes | Set this input to true in order to download latest version of the template repository (else it will reuse the SHA from last update) | | 20 | | update | | Set this input to Y in order to update AL-Go System Files if needed | N | 21 | | updateBranch | | Set the branch to update. In case `directCommit` parameter is set to true, then the branch the action is run on will be updated | github.ref_name | 22 | | directCommit | | True if the action should create a direct commit against the branch or false to create a Pull Request | false | 23 | 24 | ## OUTPUT 25 | 26 | none 27 | -------------------------------------------------------------------------------- /Actions/CheckForUpdates/action.yaml: -------------------------------------------------------------------------------- 1 | name: Check For Updates 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | actor: 9 | description: The GitHub actor running the action 10 | required: false 11 | default: ${{ github.actor }} 12 | token: 13 | description: The GitHub token running the action 14 | required: false 15 | default: ${{ github.token }} 16 | templateUrl: 17 | description: URL of the template repository (default is the template repository used to create the repository) 18 | required: false 19 | default: '' 20 | downloadLatest: 21 | description: Set this input to true in order to download latest version of the template repository (else it will reuse the SHA from last update) 22 | required: true 23 | update: 24 | description: Set this input to Y in order to update AL-Go System Files if needed 25 | required: false 26 | default: 'N' 27 | updateBranch: 28 | description: Set the branch to update 29 | required: false 30 | default: ${{ github.ref_name }} 31 | directCommit: 32 | description: Direct Commit? 33 | required: false 34 | default: 'false' 35 | runs: 36 | using: composite 37 | steps: 38 | - name: run 39 | shell: ${{ inputs.shell }} 40 | env: 41 | _actor: ${{ inputs.actor }} 42 | _token: ${{ inputs.token }} 43 | _templateUrl: ${{ inputs.templateUrl }} 44 | _downloadLatest: ${{ inputs.downloadLatest }} 45 | _update: ${{ inputs.update }} 46 | _updateBranch: ${{ inputs.updateBranch }} 47 | _directCommit: ${{ inputs.directCommit }} 48 | run: | 49 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "CheckForUpdates" -Action { 50 | ${{ github.action_path }}/CheckForUpdates.ps1 -actor $ENV:_actor -token $ENV:_token -templateUrl $ENV:_templateUrl -downloadLatest ($ENV:_downloadLatest -eq 'true') -update $ENV:_update -updateBranch $ENV:_updateBranch -directCommit ($ENV:_directCommit -eq 'true') 51 | } 52 | branding: 53 | icon: terminal 54 | color: blue 55 | -------------------------------------------------------------------------------- /Actions/CreateApp/AppTemplate/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /Actions/CreateApp/AppTemplate/HelloWorld.Test.al: -------------------------------------------------------------------------------- 1 | codeunit 50100 "HelloWorld Test" 2 | { 3 | Subtype = Test; 4 | 5 | [Test] 6 | [HandlerFunctions('HelloWorldMessageHandler')] 7 | procedure TestHelloWorldMessage() 8 | var 9 | CustList: TestPage "Customer List"; 10 | begin 11 | CustList.OpenView(); 12 | CustList.Close(); 13 | if (not MessageDisplayed) then 14 | ERROR('Message was not displayed!'); 15 | end; 16 | 17 | [MessageHandler] 18 | procedure HelloWorldMessageHandler(Message: Text[1024]) 19 | begin 20 | MessageDisplayed := MessageDisplayed or (Message = 'App published: Hello world'); 21 | end; 22 | 23 | var 24 | MessageDisplayed: Boolean; 25 | } 26 | -------------------------------------------------------------------------------- /Actions/CreateApp/AppTemplate/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // Welcome to your new AL extension. 2 | // Remember that object names and IDs should be unique across all extensions. 3 | // AL snippets start with t*, like tpageext - give them a try and happy coding! 4 | 5 | pageextension 50100 CustomerListExt extends "Customer List" 6 | { 7 | trigger OnOpenPage(); 8 | begin 9 | Message('App published: Hello world'); 10 | end; 11 | } 12 | -------------------------------------------------------------------------------- /Actions/CreateApp/AppTemplate/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "364f68de-c52e-43d5-a70b-10a278d8a086", 3 | "name": "SampleALProject", 4 | "publisher": "Default publisher", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [], 14 | "screenshots": [], 15 | "platform": "1.0.0.0", 16 | "application": "22.0.0.0", 17 | "idRanges": [ 18 | { 19 | "from": 50100, 20 | "to": 50149 21 | } 22 | ], 23 | "features": [ 24 | "NoImplicitWith" 25 | ], 26 | "resourceExposurePolicy": { 27 | "allowDebugging": true, 28 | "allowDownloadingSource": false, 29 | "includeSourceInSymbolFile": false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Actions/CreateApp/AppTemplate/bcptSuite.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "10UserTest", 3 | "description": "10 User Test", 4 | "durationInMinutes": 5, 5 | "defaultMinimumUserDelayInMilliSeconds": 120, 6 | "oneDayCorrespondsToInMinutes": 10, 7 | "tag": "10UserTest", 8 | "bcptSuiteLines": [ 9 | { 10 | "codeunitID": 149107, 11 | "numberOfSessions": 1, 12 | "description": "BCPT Detail Trial Bal. Report", 13 | "minimumUserDelay": 100, 14 | "maximumUserDelay": 1000, 15 | "delayBetweenIterations": 10, 16 | "delayType": "Fixed", 17 | "runInForeground": false 18 | }, 19 | { 20 | "codeunitID": 149103, 21 | "numberOfSessions": 1, 22 | "description": "BCPT Create PO with N Lines", 23 | "minimumUserDelay": 100, 24 | "maximumUserDelay": 1000, 25 | "delayBetweenIterations": 5, 26 | "delayType": "Fixed", 27 | "runInForeground": false, 28 | "parameters": "Lines=10" 29 | }, 30 | { 31 | "codeunitID": 149105, 32 | "numberOfSessions": 1, 33 | "description": "BCPT Create SQ with N Lines", 34 | "minimumUserDelay": 100, 35 | "maximumUserDelay": 1000, 36 | "delayBetweenIterations": 5, 37 | "delayType": "Fixed", 38 | "runInForeground": false, 39 | "parameters": "Lines=10" 40 | }, 41 | { 42 | "codeunitID": 149104, 43 | "numberOfSessions": 1, 44 | "description": "BCPT Create SO with N Lines", 45 | "minimumUserDelay": 100, 46 | "maximumUserDelay": 1000, 47 | "delayBetweenIterations": 5, 48 | "delayType": "Fixed", 49 | "runInForeground": false, 50 | "parameters": "Lines=10" 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /Actions/CreateApp/README.md: -------------------------------------------------------------------------------- 1 | # Create a new app 2 | 3 | Create a new app and add it to an AL-Go repository 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | actor | | The GitHub actor running the action | github.actor | 17 | | token | | The GitHub token running the action | github.token | 18 | | project | | Project name if the repository is setup for multiple projects | . | 19 | | type | Yes | Type of app to add (PTE, AppSource App, Test App) | | 20 | | name | Yes | App Name | | 21 | | publisher | Yes | Publisher | | 22 | | idrange | Yes | ID range | | 23 | | sampleCode | | Include Sample Code? | false | 24 | | sampleSuite | | Include Sample BCPT Suite? | false | 25 | | updateBranch | | Which branch should the app be added to | github.ref_name | 26 | | directCommit | | true if the action should create a direct commit against the branch or false to create a Pull Request | false | 27 | 28 | ## OUTPUT 29 | 30 | none 31 | -------------------------------------------------------------------------------- /Actions/CreateDevelopmentEnvironment/CreateDevelopmentEnvironment.ps1: -------------------------------------------------------------------------------- 1 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'GitHub Secrets are transferred as plain text')] 2 | Param( 3 | [Parameter(HelpMessage = "The GitHub actor running the action", Mandatory = $false)] 4 | [string] $actor, 5 | [Parameter(HelpMessage = "The GitHub token running the action", Mandatory = $false)] 6 | [string] $token, 7 | [Parameter(HelpMessage = "Name of the online environment", Mandatory = $true)] 8 | [string] $environmentName, 9 | [Parameter(HelpMessage = "Project name if the repository is setup for multiple projects", Mandatory = $false)] 10 | [string] $project = '.', 11 | [Parameter(HelpMessage = "Admin center API credentials", Mandatory = $false)] 12 | [string] $adminCenterApiCredentials, 13 | [Parameter(HelpMessage = "Reuse environment if it exists?", Mandatory = $false)] 14 | [bool] $reUseExistingEnvironment, 15 | [Parameter(HelpMessage = "Set the branch to update", Mandatory = $false)] 16 | [string] $updateBranch, 17 | [Parameter(HelpMessage = "Direct Commit?", Mandatory = $false)] 18 | [bool] $directCommit 19 | ) 20 | 21 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 22 | $serverUrl, $branch = CloneIntoNewFolder -actor $actor -token $token -updateBranch $updateBranch -DirectCommit $directCommit -newBranchPrefix 'create-development-environment' 23 | $baseFolder = (Get-Location).Path 24 | DownloadAndImportBcContainerHelper -baseFolder $baseFolder 25 | 26 | $adminCenterApiCredentials = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($adminCenterApiCredentials)) 27 | CreateDevEnv ` 28 | -kind cloud ` 29 | -caller GitHubActions ` 30 | -environmentName $environmentName ` 31 | -reUseExistingEnvironment:$reUseExistingEnvironment ` 32 | -baseFolder $baseFolder ` 33 | -project $project ` 34 | -adminCenterApiCredentials ($adminCenterApiCredentials | ConvertFrom-Json | ConvertTo-HashTable) 35 | 36 | CommitFromNewFolder -serverUrl $serverUrl -commitMessage "Create a development environment $environmentName" -branch $branch | Out-Null 37 | -------------------------------------------------------------------------------- /Actions/CreateDevelopmentEnvironment/README.md: -------------------------------------------------------------------------------- 1 | # Create Development Environment 2 | 3 | Create an online development environment 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | actor | | The GitHub actor running the action | github.actor | 17 | | token | | The GitHub token running the action | github.token | 18 | | environmentName | Yes | Name of the online environment to create | 19 | | project | | Project name if the repository is setup for multiple projects | . | 20 | | adminCenterApiCredentials | | ClientId/ClientSecret or Refresh token for Admin Center API authentication | | 21 | | reUseExistingEnvironment | | Reuse existing environment if it exists? | false | 22 | | updateBranch | | Which branch should the app be added to | github.ref_name | 23 | | directCommit | | true if the action should create a direct commit against the branch or false to create a Pull Request | false | 24 | 25 | ## OUTPUT 26 | 27 | none 28 | -------------------------------------------------------------------------------- /Actions/CreateReleaseNotes/README.md: -------------------------------------------------------------------------------- 1 | # Creates release notes 2 | 3 | Creates release notes for a release, based on a given tag and the tag from the latest release 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | token | | The GitHub token running the action | github.token | 17 | | buildVersion | Yes | Build version | | 18 | | tag_name | Yes | This release tag name | | 19 | | target_commitish | | Last commit to include in release notes | Latest | 20 | 21 | ## OUTPUT 22 | 23 | ### ENV variables 24 | 25 | none 26 | 27 | ### OUTPUT variables 28 | 29 | | Name | Description | 30 | | :-- | :-- | 31 | | ReleaseVersion | The release version | 32 | | ReleaseNotes | Release notes generated based on the changes | 33 | -------------------------------------------------------------------------------- /Actions/CreateReleaseNotes/action.yaml: -------------------------------------------------------------------------------- 1 | name: Create Release Notes 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | buildVersion: 13 | description: Build version 14 | required: true 15 | tag_name: 16 | description: Tag name 17 | required: true 18 | target_commitish: 19 | description: Last commit to include in release notes 20 | required: false 21 | default: '' 22 | outputs: 23 | ReleaseVersion: 24 | description: The release version 25 | value: ${{ steps.createreleasenotes.outputs.releaseVersion }} 26 | ReleaseNotes: 27 | description: Release note generated based on the changes 28 | value: ${{ steps.createreleasenotes.outputs.ReleaseNotes }} 29 | runs: 30 | using: composite 31 | steps: 32 | - name: run 33 | shell: ${{ inputs.shell }} 34 | id: createreleasenotes 35 | env: 36 | _token: ${{ inputs.token }} 37 | _buildVersion: ${{ inputs.buildVersion }} 38 | _tag_name: ${{ inputs.tag_name }} 39 | _target_commitish: ${{ inputs.target_commitish }} 40 | run: | 41 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "CreateReleaseNotes" -Action { 42 | ${{ github.action_path }}/CreateReleaseNotes.ps1 -token $ENV:_token -buildVersion $ENV:_buildVersion -tag_name $ENV:_tag_name -target_commitish $ENV:_target_commitish 43 | } 44 | branding: 45 | icon: terminal 46 | color: blue 47 | -------------------------------------------------------------------------------- /Actions/Deliver/README.md: -------------------------------------------------------------------------------- 1 | # Deliver 2 | 3 | Deliver App to deliveryTarget (AppSource, Storage, or...) 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with delivery target context secrets must be read by a prior call to the ReadSecrets Action | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | token | | The GitHub token running the action | github.token | 20 | | projects | | Comma-separated list of projects to deliver | * | 21 | | deliveryTarget | Yes | Delivery target (AppSource, Storage, GitHubPackages,...) | | 22 | | artifacts | Yes | The artifacts to deliver or a folder in which the artifacts have been downloaded | | 23 | | type | | Type of delivery (CD or Release) | CD | 24 | | atypes | | Artifact types to deliver | Apps,Dependencies,TestApps | 25 | | goLive | | Only relevant for AppSource delivery type. Promote AppSource App to Go Live? | false | 26 | 27 | ## OUTPUT 28 | 29 | none 30 | -------------------------------------------------------------------------------- /Actions/Deliver/action.yaml: -------------------------------------------------------------------------------- 1 | name: Deliver 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | projects: 13 | description: Projects to deliver (default is all) 14 | required: false 15 | default: '*' 16 | deliveryTarget: 17 | description: Delivery target (AppSource or Storage) 18 | required: true 19 | artifacts: 20 | description: The artifacts to deliver or a folder in which the artifacts have been downloaded 21 | required: true 22 | type: 23 | description: Type of delivery (CD or Release) 24 | required: false 25 | default: 'CD' 26 | atypes: 27 | description: Types of artifacts to deliver (Apps,Dependencies,TestApps) 28 | required: false 29 | default: 'Apps,Dependencies,TestApps' 30 | goLive: 31 | description: Promote AppSource App to Go Live? 32 | required: false 33 | default: 'false' 34 | runs: 35 | using: composite 36 | steps: 37 | - name: run 38 | shell: ${{ inputs.shell }} 39 | env: 40 | _token: ${{ inputs.token }} 41 | _projects: ${{ inputs.projects }} 42 | _deliveryTarget: ${{ inputs.deliveryTarget }} 43 | _artifacts: ${{ inputs.artifacts }} 44 | _type: ${{ inputs.type }} 45 | _atypes: ${{ inputs.atypes }} 46 | _goLive: ${{ inputs.goLive }} 47 | run: | 48 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "Deliver" -Action { 49 | ${{ github.action_path }}/Deliver.ps1 -token $ENV:_token -projects $ENV:_projects -deliveryTarget $ENV:_deliveryTarget -artifacts $ENV:_artifacts -type $ENV:_type -atypes $ENV:_atypes -goLive ($ENV:_goLive -eq 'true') 50 | } 51 | branding: 52 | icon: terminal 53 | color: blue 54 | -------------------------------------------------------------------------------- /Actions/Deploy/Deploy.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get the head ref from a PR 4 | .PARAMETER repository 5 | Repository to search in 6 | .PARAMETER prId 7 | The PR Id 8 | .PARAMETER token 9 | Auth token 10 | #> 11 | function GetHeadRefFromPRId { 12 | Param( 13 | [Parameter(Mandatory = $true)] 14 | [string] $repository, 15 | [Parameter(Mandatory = $true)] 16 | [string] $prId, 17 | [Parameter(Mandatory = $true)] 18 | [string] $token 19 | ) 20 | 21 | $headers = GetHeaders -token $token 22 | 23 | $pullsURI = "https://api.github.com/repos/$repository/pulls/$prId" 24 | Write-Host "- $pullsURI" 25 | $pr = (InvokeWebRequest -Headers $headers -Uri $pullsURI).Content | ConvertFrom-Json 26 | 27 | return $pr.head.ref 28 | } 29 | -------------------------------------------------------------------------------- /Actions/Deploy/README.md: -------------------------------------------------------------------------------- 1 | # Deploy 2 | 3 | Deploy Apps to online environment 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with delivery target context secrets must be read by a prior call to the ReadSecrets Action | 13 | | deviceCode | When deploying to a single environment which doesn't have an AuthContext, we will wait for the user to finalize the deviceflow with this deviceCode | 14 | 15 | ### Parameters 16 | 17 | | Name | Required | Description | Default value | 18 | | :-- | :-: | :-- | :-- | 19 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 20 | | environmentName | Yes | Name of environment to deploy to | 21 | | artifactsFolder | Yes | Path to the downloaded artifacts to deploy | | 22 | | type | | Type of delivery (CD or Release) | CD | 23 | | deploymentEnvironmentsJson | Yes | The settings for all Deployment Environments | | 24 | 25 | ## OUTPUT 26 | 27 | | Name | Description | 28 | | :-- | :-- | 29 | | environmentUrl | The URL for the environment. This URL is presented in the Deploy Step in summary under the environment name | 30 | -------------------------------------------------------------------------------- /Actions/Deploy/action.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | environmentName: 13 | description: Name of environment to deploy to 14 | required: true 15 | artifactsFolder: 16 | description: Path to the downloaded artifacts to deploy 17 | required: true 18 | type: 19 | description: Type of deployment (CD or Publish) 20 | required: false 21 | default: 'CD' 22 | deploymentEnvironmentsJson: 23 | description: The settings for all Deployment Environments 24 | required: true 25 | artifactsVersion: 26 | description: Artifacts version. Used to check if this is a deployment from a PR 27 | required: false 28 | default: '' 29 | outputs: 30 | environmentUrl: 31 | description: The URL of the deployed environment 32 | value: ${{ steps.Deploy.outputs.environmentUrl }} 33 | runs: 34 | using: composite 35 | steps: 36 | - name: run 37 | shell: ${{ inputs.shell }} 38 | id: Deploy 39 | env: 40 | _token: ${{ inputs.token }} 41 | _environmentName: ${{ inputs.environmentName }} 42 | _artifactsFolder: ${{ inputs.artifactsFolder }} 43 | _type: ${{ inputs.type }} 44 | _deploymentEnvironmentsJson: ${{ inputs.deploymentEnvironmentsJson }} 45 | _artifactsVersion: ${{ inputs.artifactsVersion }} 46 | run: | 47 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "Deploy" -Action { 48 | ${{ github.action_path }}/Deploy.ps1 -token $ENV:_token -environmentName $ENV:_environmentName -artifactsFolder $ENV:_artifactsFolder -type $ENV:_type -deploymentEnvironmentsJson $ENV:_deploymentEnvironmentsJson -artifactsVersion $ENV:_artifactsVersion 49 | } 50 | branding: 51 | icon: terminal 52 | color: blue 53 | -------------------------------------------------------------------------------- /Actions/DeployPowerPlatform/DeterminePowerPlatformSolutionFolder.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $artifactsFolder, 3 | [string] $solutionFolder 4 | ) 5 | 6 | if ($artifactsFolder -ne '') { 7 | $artifactsFiles = Get-ChildItem -Path (Join-Path $ENV:GITHUB_WORKSPACE $artifactsFolder) -Recurse -File | Select-Object -ExpandProperty FullName 8 | foreach($filePath in $artifactsFiles){ 9 | ## Find file containing Power Platform keyword 10 | if($filePath.contains("-PowerPlatformSolution-")){ 11 | Write-Host "Power Platform solution file:"$filePath 12 | Add-Content -encoding utf8 -path $env:GITHUB_ENV -value "powerPlatformSolutionFilePath=$filePath" 13 | Add-Content -encoding utf8 -path $env:GITHUB_ENV -value "powerPlatformSolutionFolder=.artifacts/_tempPPSolution/source" 14 | return 15 | } 16 | } 17 | throw "Not able to find Power Platform solution file in $artifactFolder that contains the artifact keyword '-PowerPlatformSolution-'" 18 | } 19 | elseif ($solutionFolder -ne '') { 20 | Add-Content -encoding utf8 -path $env:GITHUB_ENV -value "powerPlatformSolutionFolder=$solutionFolder" 21 | } 22 | else { 23 | throw "No artifactsFolder or solutionFolder specified" 24 | } 25 | -------------------------------------------------------------------------------- /Actions/DeployPowerPlatform/README.md: -------------------------------------------------------------------------------- 1 | # Deploy Power Platform 2 | 3 | Deploy the Power Platform solution from the artifacts folder 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with delivery target context secrets must be read by a prior call to the ReadSecrets Action | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | environmentName | Yes | Name of environment to deploy to | 20 | | artifactsFolder | | Path to the downloaded artifacts to deploy (when deploying from a build) | | 21 | | solutionFolder | | Path to the unpacked solutions to deploy (when deploying from branch) | | 22 | | deploymentEnvironmentsJson | Yes | The settings for all Deployment Environments | | 23 | 24 | Either artifactsFolder or solutionFolder needs to be specified 25 | 26 | ## OUTPUT 27 | 28 | | Name | Description | 29 | | :-- | :-- | 30 | | environmentUrl | The URL for the environment. This URL is presented in the Deploy Step in summary under the environment name | 31 | -------------------------------------------------------------------------------- /Actions/DetermineArtifactUrl/DetermineArtifactUrl.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "Project folder", Mandatory = $false)] 3 | [string] $project = "." 4 | ) 5 | 6 | #region Action: Setup 7 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 8 | DownloadAndImportBcContainerHelper 9 | #endregion 10 | 11 | #region Action: Determine artifacts to use 12 | $settings = $env:Settings | ConvertFrom-Json | ConvertTo-HashTable 13 | $settings = AnalyzeRepo -settings $settings -project $project -doNotCheckArtifactSetting -doNotIssueWarnings 14 | $artifactUrl = DetermineArtifactUrl -projectSettings $settings 15 | $artifactCacheKey = '' 16 | if ($settings.useCompilerFolder) { 17 | $artifactCacheKey = $artifactUrl.Split('?')[0] 18 | } 19 | #endregion 20 | 21 | #region Action: Output 22 | # Set output variables 23 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "artifact=$artifactUrl" 24 | Write-Host "artifact=$artifactUrl" 25 | Add-Content -Encoding UTF8 -Path $env:GITHUB_ENV -Value "artifactCacheKey=$artifactCacheKey" 26 | Write-Host "artifactCacheKey=$artifactCacheKey" 27 | #endregion 28 | -------------------------------------------------------------------------------- /Actions/DetermineArtifactUrl/README.md: -------------------------------------------------------------------------------- 1 | # Determine artifactUrl 2 | 3 | Determines the artifactUrl to use for a given project 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | project | | Project folder if repository is setup for multiple projects | . | 19 | 20 | ## OUTPUT 21 | 22 | ### ENV variables 23 | 24 | | Name | Description | 25 | | :-- | :-- | 26 | | artifact | The ArtifactUrl to use for the build | 27 | | artifactCacheKey | The Cache Key to use for caching the artifacts when using CompilerFolder | 28 | -------------------------------------------------------------------------------- /Actions/DetermineArtifactUrl/action.yaml: -------------------------------------------------------------------------------- 1 | name: Determine ArtifactUrl 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | project: 9 | description: Project folder 10 | required: false 11 | default: '.' 12 | runs: 13 | using: composite 14 | steps: 15 | - name: run 16 | shell: ${{ inputs.shell }} 17 | env: 18 | _project: ${{ inputs.project }} 19 | run: | 20 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "DetermineArtifactUrl" -Action { 21 | ${{ github.action_path }}/DetermineArtifactUrl.ps1 -project $ENV:_project 22 | } 23 | branding: 24 | icon: terminal 25 | color: blue 26 | -------------------------------------------------------------------------------- /Actions/DetermineArtifactsForRelease/README.md: -------------------------------------------------------------------------------- 1 | # Determine artifacts for release 2 | 3 | Determine artifacts for a release based on build version and projects. 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | buildVersion | Yes | Build version to find artifacts for | | 19 | | GITHUB_TOKEN | Yes | The GitHub token | | 20 | | TOKENFORPUSH | Yes | The GhTokenWorkflow or the GitHub token (based on UseGhTokenWorkflow for PR/Commit) | | 21 | | ProjectsJson | Yes | Json structure containing projects to search for | | 22 | 23 | ## OUTPUT 24 | 25 | ### ENV variables 26 | 27 | none 28 | 29 | ### OUTPUT variables 30 | 31 | | Name | Description | 32 | | :-- | :-- | 33 | | artifacts | The artifacts to publish on the release | 34 | | commitish | The target commitish for the release | 35 | -------------------------------------------------------------------------------- /Actions/DetermineArtifactsForRelease/action.yaml: -------------------------------------------------------------------------------- 1 | name: Determine artifacts for release 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | buildVersion: 9 | description: Build version to find artifacts for 10 | required: true 11 | GITHUB_TOKEN: 12 | description: The GitHub token 13 | required: true 14 | TOKENFORPUSH: 15 | description: The GhTokenWorkflow or the GitHub token (based on UseGhTokenWorkflow for PR/Commit) 16 | required: true 17 | ProjectsJson: 18 | description: Json structure containing projects to search for 19 | required: true 20 | outputs: 21 | artifacts: 22 | description: The artifacts to publish on the release 23 | value: ${{ steps.determineArtifactsForRelease.outputs.artifacts }} 24 | commitish: 25 | description: The target commitish for the release 26 | value: ${{ steps.determineArtifactsForRelease.outputs.commitish }} 27 | runs: 28 | using: composite 29 | steps: 30 | - name: run 31 | shell: ${{ inputs.shell }} 32 | id: determineArtifactsForRelease 33 | env: 34 | _buildVersion: ${{ inputs.buildVersion }} 35 | _GITHUB_TOKEN: ${{ inputs.GITHUB_TOKEN }} 36 | _TOKENFORPUSH: ${{ inputs.TOKENFORPUSH }} 37 | _ProjectsJson: ${{ inputs.ProjectsJson }} 38 | run: | 39 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "DetermineArtifactsForRelease" -Action { 40 | ${{ github.action_path }}/DetermineArtifactsForRelease.ps1 -buildVersion $ENV:_buildVersion -GITHUB_TOKEN $ENV:_GITHUB_TOKEN -TOKENFORPUSH $ENV:_TOKENFORPUSH -ProjectsJson $ENV:_ProjectsJson 41 | } 42 | branding: 43 | icon: terminal 44 | color: blue 45 | -------------------------------------------------------------------------------- /Actions/DetermineBuildProject/README.md: -------------------------------------------------------------------------------- 1 | # Determine whether to build project 2 | 3 | Determine whether to build project 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | token | | The GitHub token running the action | github.token | 19 | | skippedProjectsJson | Yes | Compressed JSON string containing the list of projects that should be skipped | | 20 | | project | Yes | Name of the project to build | | 21 | | baselineWorkflowRunId | Yes | Id of the baseline workflow run, from which to download artifacts if build is skipped | | 22 | 23 | ## OUTPUT 24 | 25 | ### ENV variables 26 | 27 | none 28 | 29 | ### OUTPUT variables 30 | 31 | | Name | Description | 32 | | :-- | :-- | 33 | | BuildIt | True if the project should be built | 34 | -------------------------------------------------------------------------------- /Actions/DetermineBuildProject/action.yaml: -------------------------------------------------------------------------------- 1 | name: Determine whether to Build Project 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | skippedProjectsJson: 13 | description: Compressed JSON string containing the list of projects that should be skipped 14 | required: true 15 | project: 16 | description: Name of the project to build 17 | required: true 18 | baselineWorkflowRunId: 19 | description: Id of the baseline workflow run, from which to download artifacts if build is skipped 20 | required: true 21 | outputs: 22 | BuildIt: 23 | description: Determines whether the project needs to be built 24 | value: ${{ steps.determineBuildProject.outputs.BuildIt }} 25 | runs: 26 | using: composite 27 | steps: 28 | - name: run 29 | shell: ${{ inputs.shell }} 30 | id: determineBuildProject 31 | env: 32 | _token: ${{ inputs.token }} 33 | _skippedProjectsJson: ${{ inputs.skippedProjectsJson }} 34 | _project: ${{ inputs.project }} 35 | _baselineWorkflowRunId: ${{ inputs.baselineWorkflowRunId }} 36 | run: | 37 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "DetermineBuildProject" -Action { 38 | ${{ github.action_path }}/DetermineBuildProject.ps1 -token $env:_token -skippedProjectsJson $env:_skippedProjectsJson -project $env:_project -baselineWorkflowRunId $env:_baselineWorkflowRunId 39 | } 40 | branding: 41 | icon: terminal 42 | color: blue 43 | -------------------------------------------------------------------------------- /Actions/DetermineDeliveryTargets/README.md: -------------------------------------------------------------------------------- 1 | # Determine Delivery Targets 2 | 3 | Determines the delivery targets to use for the build 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with delivery target context secrets must be read by a prior call to the ReadSecrets Action (if checkContextSecrets is set to Y) | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | projectsJson | | Projects folder if repository is setup for multiple projects | . | 20 | | checkContextSecrets | | Determines whether to check that delivery targets have a corresponding context secret defined | true | 21 | 22 | ## OUTPUT 23 | 24 | | Name | Description | 25 | | :-- | :-- | 26 | | deliveryTargets | Compressed JSON array containing all delivery targets to use for the build | 27 | | contextSecrets | A comma-separated string with the names of the secrets to pass to ReadSecrets | 28 | 29 | ### ENV variables 30 | -------------------------------------------------------------------------------- /Actions/DetermineDeliveryTargets/action.yaml: -------------------------------------------------------------------------------- 1 | name: Determine Delivery Targets 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | projectsJson: 9 | description: Projects to investigate 10 | required: false 11 | default: '["."]' 12 | checkContextSecrets: 13 | description: Check whether context secret exists? 14 | required: false 15 | default: 'false' 16 | outputs: 17 | DeliveryTargetsJson: 18 | description: An array of Delivery Targets in compressed JSON format 19 | value: ${{ steps.determineDeliveryTargets.outputs.DeliveryTargetsJson }} 20 | ContextSecrets: 21 | description: A comma-separated list of Context Secret names used 22 | value: ${{ steps.determineDeliveryTargets.outputs.ContextSecrets }} 23 | runs: 24 | using: composite 25 | steps: 26 | - name: run 27 | shell: ${{ inputs.shell }} 28 | id: determineDeliveryTargets 29 | env: 30 | _projectsJson: ${{ inputs.projectsJson }} 31 | _checkContextSecrets: ${{ inputs.checkContextSecrets }} 32 | run: | 33 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "DetermineDeliveryTargets" -Action { 34 | ${{ github.action_path }}/DetermineDeliveryTargets.ps1 -projectsJson $ENV:_projectsJson -checkContextSecrets ($ENV:_checkContextSecrets -eq 'true') 35 | } 36 | branding: 37 | icon: terminal 38 | color: blue 39 | -------------------------------------------------------------------------------- /Actions/DetermineDeploymentEnvironments/README.md: -------------------------------------------------------------------------------- 1 | # Determine Deployment Environments 2 | 3 | Determines the environments to be used for a build or a publish 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | GITHUB_TOKEN | GITHUB_TOKEN must be set as an environment variable when calling this action | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | getEnvironments | Yes | Specifies the pattern of the environments you want to retrieve (\* for all) | | 20 | | type | Yes | Type of deployment to get environments for (CD, Publish or All) | | 21 | 22 | ## OUTPUT 23 | 24 | | EnvironmentsMatrixJson | The Environment matrix to use for the Deploy step in compressed JSON format | 25 | | DeploymentEnvironmentsJson | Deployment Environments with settings in compressed JSON format | 26 | | EnvironmentCount | Number of Deployment Environments | 27 | | UnknownEnvironment | Flag determining whether we try to publish to an unknown environment (invoke device code flow) | 28 | | GenerateALDocArtifact | Flag determining whether to generate the ALDoc artifact | 29 | | DeployALDocArtifact | Flag determining whether to deploy the ALDoc artifact to GitHub Pages | 30 | 31 | ### ENV variables 32 | -------------------------------------------------------------------------------- /Actions/DetermineDeploymentEnvironments/action.yaml: -------------------------------------------------------------------------------- 1 | name: Determine Deployment Environments 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | getEnvironments: 9 | description: Specifies the pattern of the environments you want to retreive (* for all) 10 | required: true 11 | type: 12 | description: Type of deployment (CD, Publish or All) 13 | required: true 14 | outputs: 15 | EnvironmentsMatrixJson: 16 | description: The Environment matrix to use for the Deploy step in compressed JSON format 17 | value: ${{ steps.determineDeploymentEnvironments.outputs.EnvironmentsMatrixJson }} 18 | DeploymentEnvironmentsJson: 19 | description: Deployment Environments with settings in compressed JSON format 20 | value: ${{ steps.determineDeploymentEnvironments.outputs.DeploymentEnvironmentsJson }} 21 | EnvironmentCount: 22 | description: Number of Deployment Environments 23 | value: ${{ steps.determineDeploymentEnvironments.outputs.EnvironmentCount }} 24 | UnknownEnvironment: 25 | description: Flag determining whether the environment is unknown 26 | value: ${{ steps.determineDeploymentEnvironments.outputs.UnknownEnvironment }} 27 | GenerateALDocArtifact: 28 | description: Flag determining whether to generate the ALDoc artifact 29 | value: ${{ steps.determineDeploymentEnvironments.outputs.GenerateALDocArtifact }} 30 | DeployALDocArtifact: 31 | description: Flag determining whether to deploy the ALDoc artifact to GitHub Pages 32 | value: ${{ steps.determineDeploymentEnvironments.outputs.DeployALDocArtifact }} 33 | runs: 34 | using: composite 35 | steps: 36 | - name: run 37 | shell: ${{ inputs.shell }} 38 | id: determineDeploymentEnvironments 39 | env: 40 | _getEnvironments: ${{ inputs.getEnvironments }} 41 | _type: ${{ inputs.type }} 42 | run: | 43 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "DetermineDeploymentEnvironments" -Action { 44 | ${{ github.action_path }}/DetermineDeploymentEnvironments.ps1 -getEnvironments $ENV:_getEnvironments -type $ENV:_type 45 | } 46 | branding: 47 | icon: terminal 48 | color: blue 49 | -------------------------------------------------------------------------------- /Actions/DetermineProjectsToBuild/README.md: -------------------------------------------------------------------------------- 1 | # Determine projects to build 2 | 3 | Scans for AL-Go projects and determines which one to build 4 | 5 | The action also computes build dimensions, based on the projects and the build modes for each of them 6 | 7 | ## INPUT 8 | 9 | ### ENV variables 10 | 11 | none 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | maxBuildDepth | | Specifies the maximum build depth suppored by the workflow running the action | 0 | 19 | 20 | ## OUTPUT 21 | 22 | ### ENV variables 23 | 24 | none 25 | 26 | ### OUTPUT variables 27 | 28 | | Name | Description | 29 | | :-- | :-- | 30 | | ProjectsJson | An array of AL-Go projects in compressed JSON format | 31 | | SkippedProjectsJson | An array of skipped AL-Go projects in compressed JSON format | 32 | | ProjectDependenciesJson | An object that holds the project dependencies in compressed JSON format | 33 | | BuildOrderJson | An array of objects that determine that build order, including build dimensions | 34 | | BuildAllProjects | A flag that indicates whether to build all projects or only the modified ones | 35 | | BaselineWorkflowRunId | The ID of the workflow run containing last known good build, if we are doing incremental builds | 36 | | BaselineWorkflowSHA | The SHA of the last known good build, if we are doing incremental builds | 37 | -------------------------------------------------------------------------------- /Actions/DownloadProjectDependencies/README.md: -------------------------------------------------------------------------------- 1 | # Download project dependencies 2 | 3 | Downloads artifacts from AL-Go projects, that are dependencies of a given AL-Go project 4 | 5 | The action constructs arrays of paths to .app files, that are dependencies of the apps in an AL-Go project 6 | 7 | ## INPUT 8 | 9 | ### ENV variables 10 | 11 | | Name | Description | 12 | | :-- | :-- | 13 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 14 | | Secrets | env.Secrets must be read by a prior call to the ReadSecrets Action with appDependencySecrets in getSecrets | 15 | 16 | ### Parameters 17 | 18 | | Name | Required | Description | Default value | 19 | | :-- | :-: | :-- | :-- | 20 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 21 | | project | Yes | The AL-Go project for which to download dependencies | | 22 | | buildMode | Yes | The build mode to use to downloaded to most appropriate dependencies. If a dependency project isn't built in the provided build mode, then the artifacts from the default mode will be used | | 23 | | projectDependenciesJson | Yes | A JSON-formatted object that maps a project to an array of its dependencies | | 24 | | baselineWorkflowRunId | No | The ID of the workflow run that was used as baseline for the current build | '0' | 25 | 26 | ## OUTPUT 27 | 28 | ### ENV variables 29 | 30 | | Name | Description | 31 | | :-- | :-- | 32 | | appFolders | A JSON-formatted array of appFolders | 33 | | testFolders | A JSON-formatted array of testFolders | 34 | | bcptTestFolders | A JSON-formatted array of bcptTestFolders | 35 | 36 | ### OUTPUT variables 37 | 38 | | Name | Description | 39 | | :-- | :-- | 40 | | DownloadedApps | A JSON-formatted list of paths to .app files, that dependencies of the apps | 41 | | DownloadedTestApps | A JSON-formatted list of paths to .app files, that dependencies of the test apps | 42 | -------------------------------------------------------------------------------- /Actions/DumpWorkflowInfo/DumpWorkflowInfo.ps1: -------------------------------------------------------------------------------- 1 | Write-Host "Event name: $env:GITHUB_EVENT_NAME" 2 | if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') { 3 | Write-Host "Inputs:" 4 | $eventPath = Get-Content -Encoding UTF8 -Path $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json 5 | if ($null -ne $eventPath.inputs) { 6 | $eventPath.inputs.psObject.Properties | Sort-Object { $_.Name } | ForEach-Object { 7 | $property = $_.Name 8 | $value = $eventPath.inputs."$property" 9 | Write-Host "- $property = '$value'" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Actions/DumpWorkflowInfo/README.md: -------------------------------------------------------------------------------- 1 | # Dump Workflow Info 2 | 3 | Dump workflow info 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | 17 | ## OUTPUT 18 | 19 | none 20 | -------------------------------------------------------------------------------- /Actions/DumpWorkflowInfo/action.yaml: -------------------------------------------------------------------------------- 1 | name: Dump Workflow Info 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | runs: 9 | using: composite 10 | steps: 11 | - name: run 12 | shell: ${{ inputs.shell }} 13 | run: | 14 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "DumpWorkflowInfo" -Action { 15 | ${{ github.action_path }}/DumpWorkflowInfo.ps1 16 | } 17 | branding: 18 | icon: terminal 19 | color: blue 20 | -------------------------------------------------------------------------------- /Actions/GetArtifactsForDeployment/README.md: -------------------------------------------------------------------------------- 1 | # Get artifacts for deployment 2 | 3 | Download artifacts for deployment 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | token | | The GitHub token running the action | github.token | 17 | | artifactsVersion | Yes | Artifacts version to download (current, prerelease, draft, latest or version number) | | 18 | | artifactsFolder | Yes | Folder in which the artifacts will be downloaded | | 19 | 20 | ## OUTPUT 21 | 22 | none 23 | 24 | ### ENV variables 25 | 26 | none 27 | 28 | ### OUTPUT variables 29 | 30 | none 31 | -------------------------------------------------------------------------------- /Actions/GetArtifactsForDeployment/action.yaml: -------------------------------------------------------------------------------- 1 | name: Get Artifacts for deployment 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | artifactsVersion: 13 | description: Artifacts version to download (current, prerelease, draft, latest or version number) 14 | required: true 15 | artifactsFolder: 16 | description: Folder in which the artifacts will be downloaded 17 | required: true 18 | runs: 19 | using: composite 20 | steps: 21 | - name: run 22 | shell: ${{ inputs.shell }} 23 | env: 24 | _token: ${{ inputs.token }} 25 | _artifactsVersion: ${{ inputs.artifactsVersion }} 26 | _artifactsFolder: ${{ inputs.artifactsFolder }} 27 | run: | 28 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "GetArtifactsForDeployment" -Action { 29 | ${{ github.action_path }}/GetArtifactsForDeployment.ps1 -token $ENV:_token -artifactsVersion $ENV:_artifactsVersion -artifactsFolder $ENV:_artifactsFolder 30 | } 31 | branding: 32 | icon: terminal 33 | color: blue 34 | -------------------------------------------------------------------------------- /Actions/GetWorkflowMultiRunBranches/GetWorkflowMultiRunBranches.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $false, HelpMessage = "Comma-separated value of branch name patterns to include if they exist. If not specified, only the current branch is returned. Wildcards are supported.")] 3 | [string] $includeBranches 4 | ) 5 | 6 | $gitHubHelperPath = Join-Path $PSScriptRoot '../Github-Helper.psm1' -Resolve 7 | Import-Module $gitHubHelperPath -DisableNameChecking 8 | 9 | switch ($env:GITHUB_EVENT_NAME) { 10 | 'schedule' { 11 | Write-Host "Event is schedule: getting branches from settings" 12 | $settings = ConvertFrom-Json $env:settings 13 | 14 | # Add defensive check to handle if workflowSchedule.includeBranches is not defined in settings 15 | if (($settings.PSObject.Properties.Name -eq "workflowSchedule") -and ($settings.workflowSchedule.PSObject.Properties.Name -eq "includeBranches") -and $($settings.workflowSchedule.includeBranches)) { 16 | $branchPatterns = @($($settings.workflowSchedule.includeBranches)) 17 | } 18 | else { 19 | Write-Host "No branch patterns defined in settings" 20 | $branchPatterns = @() 21 | } 22 | } 23 | 'workflow_dispatch' { 24 | Write-Host "Event is workflow_dispatch: getting branches from input" 25 | $branchPatterns = @($includeBranches.Split(',') | ForEach-Object { $_.Trim() }) 26 | } 27 | } 28 | 29 | # Default to the current branch if no branch patterns are specified 30 | if (-not $branchPatterns) { 31 | $branchPatterns = @($env:GITHUB_REF_NAME) 32 | } 33 | 34 | Write-Host "Filtering branches by: $($branchPatterns -join ', ')" 35 | 36 | invoke-git fetch --quiet 37 | $allBranches = @(invoke-git -returnValue for-each-ref --format="%(refname:short)" refs/remotes/origin | ForEach-Object { $_ -replace 'origin/', '' }) 38 | $branches = @() 39 | 40 | foreach ($branchPattern in $branchPatterns) { 41 | $branches += $allBranches | Where-Object { $_ -like $branchPattern } 42 | } 43 | 44 | $branches = @($branches | Select-Object -Unique) 45 | Write-Host "Found git branches: $($branches -join ', ')" 46 | 47 | # Add the branches to the output 48 | $ResultJSON = $(ConvertTo-Json @{ branches = $branches } -Depth 99 -Compress) 49 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "Result=$ResultJSON" 50 | -------------------------------------------------------------------------------- /Actions/GetWorkflowMultiRunBranches/README.md: -------------------------------------------------------------------------------- 1 | # Get Workflow Multi-Run Branches 2 | 3 | Gets the branches for a multi-branch workflow run. 4 | If the worflow is dispatched, the branches are determined based on the input `includeBranches`. 5 | If the workflow is run on a schedule, the branches are determined based on the `workflowSchedule.includeBranches` setting. 6 | 7 | ## INPUT 8 | 9 | ### ENV variables 10 | 11 | | Name | Description | 12 | | :-- | :-- | 13 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 14 | 15 | ### Parameters 16 | 17 | | Name | Required | Description | Default value | 18 | | :-- | :-: | :-- | :-- | 19 | | shell | false | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 20 | | includeBranches | false | Comma-separated value of branch name patterns to include if they exist. If not specified, only the current branch is returned. Wildcards are supported. |''| 21 | 22 | ## OUTPUT 23 | 24 | ### ENV variables 25 | 26 | none 27 | 28 | ### OUTPUT variables 29 | 30 | | Name | Description | 31 | | :-- | :-- | 32 | | Result | JSON-formatted object with `branches` property, an array of branch names | 33 | -------------------------------------------------------------------------------- /Actions/GetWorkflowMultiRunBranches/action.yaml: -------------------------------------------------------------------------------- 1 | name: Get Workflow Multi-Run Branches 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | includeBranches: 9 | description: Comma-separated value of branch name patterns to include if they exist. If not specified, only the current branch is returned. Wildcards are supported. 10 | required: false 11 | default: '' 12 | outputs: 13 | Result: 14 | description: JSON-formatted object with branches property, an array of branch names 15 | value: ${{ steps.GetWorkflowMultiRunBranches.outputs.Result }} 16 | runs: 17 | using: composite 18 | steps: 19 | - name: run 20 | shell: ${{ inputs.shell }} 21 | id: GetWorkflowMultiRunBranches 22 | env: 23 | _includeBranches: ${{ inputs.includeBranches }} 24 | run: | 25 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "GetWorkflowMultiRunBranches" -Action { 26 | ${{ github.action_path }}/GetWorkflowMultiRunBranches.ps1 -includeBranches $env:_includeBranches 27 | } 28 | branding: 29 | icon: terminal 30 | color: blue 31 | -------------------------------------------------------------------------------- /Actions/IncrementVersionNumber/README.md: -------------------------------------------------------------------------------- 1 | # Increment version number 2 | 3 | Increment version number in AL-Go repository 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | actor | | The GitHub actor running the action | github.actor | 19 | | token | | The GitHub token running the action | github.token | 20 | | projects | | List of project names if the repository is setup for multiple projects (\* for all projects) | * | 21 | | versionNumber | Yes | The version to update to. Use Major.Minor for absolute change, use +1 to bump to the next major version, use +0.1 to bump to the next minor version | | 22 | | updateBranch | | Which branch should the app be added to | github.ref_name | 23 | | skipUpdatingDependencies | | Skip updating dependency version numbers in all apps | false | 24 | | directCommit | | true if the action should create a direct commit against the branch or false to create a Pull Request | false | 25 | 26 | ## OUTPUT 27 | 28 | none 29 | -------------------------------------------------------------------------------- /Actions/Invoke-AlGoAction.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $true)] 3 | [string] $ActionName, 4 | [Parameter(Mandatory = $true)] 5 | [scriptblock]$Action, 6 | [Parameter(Mandatory = $false)] 7 | [switch]$SkipTelemetry, 8 | [Parameter(Mandatory = $false)] 9 | [System.Collections.Generic.Dictionary[[System.String], [System.String]]] $AdditionalData = @{} 10 | ) 11 | 12 | $errorActionPreference = "Stop" 13 | $progressPreference = "SilentlyContinue" 14 | Set-StrictMode -Version 2.0 15 | 16 | Import-Module (Join-Path -Path $PSScriptRoot -ChildPath "TelemetryHelper.psm1" -Resolve) 17 | 18 | try { 19 | $startTime = Get-Date 20 | Invoke-Command -ScriptBlock $Action 21 | 22 | if (-not $SkipTelemetry) { 23 | $AdditionalData["ActionDuration"] = (((Get-Date) - $startTime).TotalSeconds).ToString() 24 | Trace-Information -ActionName $ActionName -AdditionalData $AdditionalData 25 | } 26 | } 27 | catch { 28 | if (-not $SkipTelemetry) { 29 | $AdditionalData["ActionDuration"] = (((Get-Date) - $startTime).TotalSeconds).ToString() 30 | Trace-Exception -ActionName $ActionName -ErrorRecord $_ -AdditionalData $AdditionalData 31 | } 32 | 33 | Write-Host "::ERROR::Unexpected error when running action. Error Message: $($_.Exception.Message.Replace("`r",'').Replace("`n",' ')), StackTrace: $($_.ScriptStackTrace.Replace("`r",'').Replace("`n",' <- '))"; 34 | exit 1 35 | } 36 | -------------------------------------------------------------------------------- /Actions/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /Actions/Packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign": "0.9.1-beta.25278.1", 3 | "Microsoft.ApplicationInsights": "2.20.0", 4 | "Az.Accounts": "2.15.1", 5 | "Az.Storage": "6.1.1", 6 | "Az.KeyVault": "5.2.0" 7 | } 8 | -------------------------------------------------------------------------------- /Actions/PipelineCleanup/PipelineCleanup.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "Project folder", Mandatory = $false)] 3 | [string] $project = "." 4 | ) 5 | 6 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 7 | DownloadAndImportBcContainerHelper 8 | 9 | if ($project -eq ".") { $project = "" } 10 | 11 | $containerName = GetContainerName($project) 12 | Remove-Bccontainer $containerName 13 | -------------------------------------------------------------------------------- /Actions/PipelineCleanup/README.md: -------------------------------------------------------------------------------- 1 | # Pipeline Cleanup 2 | 3 | Perform cleanup after running pipeline in AL-Go repository 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | project | | Project name if the repository is setup for multiple projects | . | 17 | 18 | ## OUTPUT 19 | 20 | none 21 | -------------------------------------------------------------------------------- /Actions/PipelineCleanup/action.yaml: -------------------------------------------------------------------------------- 1 | name: Pipeline Cleanup 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | project: 9 | description: Project folder 10 | required: false 11 | default: '.' 12 | runs: 13 | using: composite 14 | steps: 15 | - name: run 16 | shell: ${{ inputs.shell }} 17 | env: 18 | _project: ${{ inputs.project }} 19 | run: | 20 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "PipelineCleanup" -Action { 21 | ${{ github.action_path }}/PipelineCleanup.ps1 -project $ENV:_project 22 | } 23 | branding: 24 | icon: terminal 25 | color: blue 26 | -------------------------------------------------------------------------------- /Actions/PullPowerPlatformChanges/GitCloneReponsitory.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "The GitHub actor running the action", Mandatory = $false)] 3 | [string] $actor, 4 | [Parameter(HelpMessage = "The GitHub token running the action", Mandatory = $false)] 5 | [string] $token, 6 | [Parameter(HelpMessage = "Set the branch to update", Mandatory = $false)] 7 | [string] $updateBranch, 8 | [Parameter(HelpMessage = "Direct Commit", Mandatory = $false)] 9 | [bool] $directCommit 10 | ) 11 | 12 | $ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 13 | 14 | Write-Host "Starting GitCloneRepository.ps1 with parameters: $([environment]::Newline)actor: $actor$([environment]::Newline)updateBranch: $updateBranch$([environment]::Newline)directCommit: $directCommit" 15 | 16 | # Import the helper script 17 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 18 | 19 | Write-Host "Cloning the repository into a new folder" 20 | $serverUrl, $branch = CloneIntoNewFolder -actor $actor -token $token -updateBranch $updateBranch -DirectCommit $directCommit -newBranchPrefix "pull-powerplatform-changes" 21 | $baseFolder = (Get-Location).Path 22 | 23 | Add-Content -encoding utf8 -Path $env:GITHUB_ENV -Value "clonedRepoPath=$baseFolder" 24 | Add-Content -encoding utf8 -Path $env:GITHUB_ENV -Value "serverUrl=$serverUrl" 25 | Add-Content -encoding utf8 -Path $env:GITHUB_ENV -Value "gitHubBranch=$branch" 26 | -------------------------------------------------------------------------------- /Actions/PullPowerPlatformChanges/GitCommitChanges.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "The GitHub actor running the action", Mandatory = $false)] 3 | [string] $actor, 4 | [Parameter(HelpMessage = "The GitHub token running the action", Mandatory = $false)] 5 | [string] $token, 6 | [Parameter(HelpMessage = "Name of the Power Platform solution.", Mandatory = $false)] 7 | [string] $powerPlatformSolutionName, 8 | [Parameter(HelpMessage = "The name of the environment as defined in GitHub", Mandatory = $false)] 9 | [string] $environmentName, 10 | [Parameter(HelpMessage = "The current location for files to be checked in", Mandatory = $false)] 11 | [string] $location, 12 | [Parameter(HelpMessage = "ServerUrl for Git Push", Mandatory = $false)] 13 | [string] $serverUrl, 14 | [Parameter(HelpMessage = "Branch to update", Mandatory = $false)] 15 | [string] $gitHubBranch 16 | ) 17 | 18 | $ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 19 | 20 | # Import the helper script 21 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 22 | 23 | Set-Location -Path $location 24 | 25 | # Environment variables for hub commands 26 | $env:GITHUB_USER = $actor 27 | $env:GITHUB_TOKEN = GetAccessToken -token $token -permissions @{"actions"="read";"metadata"="read";"contents"="write";"pull_requests"="write"} 28 | 29 | # Commit from the new folder 30 | Write-Host "Committing changes from the new folder $Location\$PowerPlatformSolutionName to branch $gitHubBranch" 31 | CommitFromNewFolder -ServerUrl $serverUrl -CommitMessage "Update solution: $PowerPlatformSolutionName with latest from environment: $environmentName" -Branch $gitHubBranch 32 | -------------------------------------------------------------------------------- /Actions/PullPowerPlatformChanges/README.md: -------------------------------------------------------------------------------- 1 | # Pull Power Platform Changes 2 | 3 | Pull the Power Platform solution from the specified Power Platform environment 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with delivery target context secrets must be read by a prior call to the ReadSecrets Action | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | actor | | The GitHub actor running the action | github.actor | 20 | | token | | The GitHub token running the action | github.token | 21 | | environmentName | Yes | Name of environment to pull changes from | 22 | | solutionFolder | | Name of the solution to download and folder in which to download the solution | | 23 | | deploymentEnvironmentsJson | Yes | The settings for all Deployment Environments | | 24 | | updateBranch | | The branch to update | github.ref_name | 25 | | directCommit | | true if the action should create a direct commit against the branch or false to create a Pull Request | false | 26 | 27 | Either artifactsFolder or solutionFolder needs to be specified 28 | 29 | ## OUTPUT 30 | 31 | | Name | Description | 32 | | :-- | :-- | 33 | | environmentUrl | The URL for the environment. This URL is presented in the Deploy Step in summary under the environment name | 34 | -------------------------------------------------------------------------------- /Actions/PullRequestStatusCheck/PullRequestStatusCheck.ps1: -------------------------------------------------------------------------------- 1 | function PullRequestStatusCheck() 2 | { 3 | param( 4 | [Parameter(HelpMessage = "Repository name", Mandatory = $true)] 5 | [string] $Repository, 6 | [Parameter(HelpMessage = "Run Id", Mandatory = $true)] 7 | [string] $RunId 8 | ) 9 | Write-Host "Checking PR Build status for run $RunId in repository $Repository" 10 | 11 | $workflowJobs = gh api /repos/$Repository/actions/runs/$RunId/jobs --paginate -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" | ConvertFrom-Json 12 | $failedJobs = $workflowJobs.jobs | Where-Object { $_.conclusion -eq "failure" } 13 | 14 | if ($failedJobs) { 15 | throw "PR Build failed. Failing jobs: $($failedJobs.name -join ', ')" 16 | } 17 | } 18 | 19 | PullRequestStatusCheck -Repository $env:GITHUB_REPOSITORY -RunId $env:GITHUB_RUN_ID 20 | Write-Host "PR Build succeeded" 21 | -------------------------------------------------------------------------------- /Actions/PullRequestStatusCheck/README.md: -------------------------------------------------------------------------------- 1 | # Pull Request Status Check 2 | 3 | Check the status of a pull request build and fail the build if any jobs have failed. 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | GITHUB_TOKEN | GITHUB_TOKEN must be set as an environment variable when calling this action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | 19 | ## OUTPUT 20 | 21 | none 22 | -------------------------------------------------------------------------------- /Actions/PullRequestStatusCheck/action.yaml: -------------------------------------------------------------------------------- 1 | name: Pull Request Status Check 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | runs: 9 | using: composite 10 | steps: 11 | - name: run 12 | shell: ${{ inputs.shell }} 13 | run: | 14 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "PullRequestStatusCheck" -Action { 15 | ${{ github.action_path }}/PullRequestStatusCheck.ps1 16 | } 17 | branding: 18 | icon: terminal 19 | color: blue 20 | -------------------------------------------------------------------------------- /Actions/ReadPowerPlatformSettings/README.md: -------------------------------------------------------------------------------- 1 | # Read Power Platform Settings 2 | 3 | Read settings for Power Platform deployment from settings and secrets 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with delivery target context secrets must be read by a prior call to the ReadSecrets Action | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | deploymentEnvironmentsJson | Yes | The settings for all Deployment Environments | | 20 | | environmentName | Yes | Name of environment to deploy to | | 21 | 22 | ## OUTPUT 23 | 24 | ### ENV variables 25 | 26 | none 27 | 28 | ### OUTPUT variables 29 | 30 | | Name | Description | 31 | | :-- | :-- | 32 | | ppEnvironmentUrl | Power Platform Environment URL | 33 | | ppUserName | Power Platform Username | 34 | | ppPassword | Power Platform Password | 35 | | ppApplicationId | Power Platform Application Id | 36 | | ppTenantId | Power Platform Tenant Id | 37 | | ppClientSecret | Power Platform Client Secret | 38 | | companyId | Business Central Company Id | 39 | | environmentName | Business Central Environment Name | 40 | -------------------------------------------------------------------------------- /Actions/ReadPowerPlatformSettings/action.yaml: -------------------------------------------------------------------------------- 1 | name: Read Power Platform Settings 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | deploymentEnvironmentsJson: 9 | description: The settings for all Deployment Environments 10 | required: true 11 | environmentName: 12 | description: Name of environment to deploy to 13 | required: true 14 | outputs: 15 | ppEnvironmentUrl: 16 | description: Power Platform Environment URL 17 | value: ${{ steps.ReadPowerPlatformSettings.outputs.ppEnvironmentUrl }} 18 | ppUserName: 19 | description: Power Platform Username 20 | value: ${{ steps.ReadPowerPlatformSettings.outputs.ppUserName }} 21 | ppPassword: 22 | description: Power Platform Password 23 | value: ${{ steps.ReadPowerPlatformSettings.outputs.ppPassword }} 24 | ppApplicationId: 25 | description: Power Platform Application Id 26 | value: ${{ steps.ReadPowerPlatformSettings.outputs.ppApplicationId }} 27 | ppTenantId: 28 | description: Power Platform Tenant Id 29 | value: ${{ steps.ReadPowerPlatformSettings.outputs.ppTenantId }} 30 | ppClientSecret: 31 | description: Power Platform Client Secret 32 | value: ${{ steps.ReadPowerPlatformSettings.outputs.ppClientSecret }} 33 | companyId: 34 | description: Business Central Company Id 35 | value: ${{ steps.ReadPowerPlatformSettings.outputs.companyId }} 36 | environmentName: 37 | description: Business Central Environment Name 38 | value: ${{ steps.ReadPowerPlatformSettings.outputs.environmentName }} 39 | runs: 40 | using: composite 41 | steps: 42 | - name: run 43 | shell: ${{ inputs.shell }} 44 | id: ReadPowerPlatformSettings 45 | env: 46 | _deploymentEnvironmentsJson: ${{ inputs.deploymentEnvironmentsJson }} 47 | _environmentName: ${{ inputs.environmentName }} 48 | run: | 49 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "ReadPowerPlatformSettings" -Action { 50 | ${{ github.action_path }}/ReadPowerPlatformSettings.ps1 -deploymentEnvironmentsJson $ENV:_deploymentEnvironmentsJson -environmentName $ENV:_environmentName 51 | } 52 | branding: 53 | icon: terminal 54 | color: blue 55 | -------------------------------------------------------------------------------- /Actions/ReadSecrets/README.md: -------------------------------------------------------------------------------- 1 | # Read secrets 2 | 3 | Read secrets from GitHub secrets or Azure Keyvault for AL-Go workflows 4 | The secrets read and added to the output are the secrets specified in the getSecrets parameter 5 | Additionally, the secrets specified by the authTokenSecret in AppDependencyProbingPaths and TrustedNuGetFeeds are read if appDependencySecrets is specified in getSecrets 6 | All secrets included in the Secrets output are Base64 encoded to avoid issues with national characters 7 | Secrets, which name is preceded by an asterisk (\*) are encrypted and Base64 encoded 8 | 9 | ## INPUT 10 | 11 | ### ENV variables 12 | 13 | | Name | Description | 14 | | :-- | :-- | 15 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 16 | 17 | ### Parameters 18 | 19 | | Name | Required | Description | Default value | 20 | | :-- | :-: | :-- | :-- | 21 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 22 | | gitHubSecrets | Yes | GitHub secrets in a json structure | | 23 | | getSecrets | Yes | Comma-separated list of secrets to get (add appDependencySecrets to request secrets needed for resolving dependencies in AppDependencyProbingPaths and TrustedNuGetFeeds, add TokenForPush in order to request a token to use for pull requests and commits). Secrets preceded by an asterisk are returned encrypted | | 24 | | useGhTokenWorkflowForPush | false | Determines whether you want to use the GhTokenWorkflow secret for TokenForPush | false | 25 | 26 | ## OUTPUT 27 | 28 | ### ENV variables 29 | 30 | none 31 | 32 | ### OUTPUT variables 33 | 34 | | Name | Description | 35 | | :-- | :-- | 36 | | Secrets | A compressed json construct with all requested secrets base64 encoded. Secrets preceded by an asterisk (\*) are encrypted before base64 encoding. The secret value + the base64 value of the secret value are masked in the log | 37 | | TokenForPush | The token to use when workflows are pushing changes (either directly, or via pull requests). This is either the GITHUB_TOKEN or the GhTokenWorkflow secret (based on the env variable useGhTokenWorkflowForPush) | 38 | -------------------------------------------------------------------------------- /Actions/ReadSecrets/action.yaml: -------------------------------------------------------------------------------- 1 | name: Read Secrets 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | gitHubSecrets: 9 | description: All GitHub Secrets in compressed JSON format 10 | required: true 11 | getSecrets: 12 | description: Comma-separated list of Secrets to get. Secrets preceded by an asterisk are returned encrypted 13 | required: true 14 | useGhTokenWorkflowForPush: 15 | description: Determines whether you want to use the GhTokenWorkflow secret for TokenForPush 16 | required: false 17 | default: 'false' 18 | outputs: 19 | Secrets: 20 | description: All requested secrets in compressed JSON format 21 | value: ${{ steps.ReadSecrets.outputs.Secrets }} 22 | TokenForPush: 23 | description: The token to use when workflows are pushing changes (either directly, or via pull requests). 24 | value: ${{ steps.ReadSecrets.outputs.TokenForPush }} 25 | runs: 26 | using: composite 27 | steps: 28 | - name: run 29 | shell: ${{ inputs.shell }} 30 | id: ReadSecrets 31 | env: 32 | _getSecrets: ${{ inputs.getSecrets }} 33 | _useGhTokenWorkflowForPush: ${{ inputs.useGhTokenWorkflowForPush }} 34 | run: | 35 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "ReadSecrets" -Action { 36 | ${{ github.action_path }}/ReadSecrets.ps1 -gitHubSecrets '${{ inputs.gitHubSecrets }}' -getSecrets $ENV:_getSecrets -useGhTokenWorkflowForPush $ENV:_useGhTokenWorkflowForPush 37 | } 38 | branding: 39 | icon: terminal 40 | color: blue 41 | -------------------------------------------------------------------------------- /Actions/ReadSettings/README.md: -------------------------------------------------------------------------------- 1 | # Read settings 2 | 3 | Read settings for AL-Go workflows 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | project | | Project name if the repository is setup for multiple projects | . | 17 | | buildMode | | Build mode. Only set when called from \_BuildALGoProject | Default | 18 | | get | | Specifies which properties to get from the settings file, default is all | | 19 | 20 | ## OUTPUT 21 | 22 | ### ENV variables 23 | 24 | | Name | Description | 25 | | :-- | :-- | 26 | | Settings | A compressed JSON structure with ALL AL-Go settings, independent of the get parameter. If project was not specified, this will only include repository settings. | 27 | 28 | > [!NOTE] 29 | > This method creates individual environment variables for every setting specified in the get parameter. 30 | 31 | ### OUTPUT variables 32 | 33 | | Name | Description | 34 | | :-- | :-- | 35 | | GitHubRunnerJson | GitHubRunner in compressed Json format | 36 | | GitHubRunnerShell | Shell for GitHubRunner jobs | 37 | -------------------------------------------------------------------------------- /Actions/ReadSettings/action.yaml: -------------------------------------------------------------------------------- 1 | name: Read Settings 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | project: 9 | description: Project folder 10 | required: false 11 | default: '.' 12 | buildMode: 13 | description: Build mode 14 | required: false 15 | default: 'Default' 16 | get: 17 | description: Specifies which properties to get from the settings file, default is all 18 | required: false 19 | default: '' 20 | outputs: 21 | GitHubRunnerJson: 22 | description: GitHubRunner in compressed Json format 23 | value: ${{ steps.readsettings.outputs.GitHubRunnerJson }} 24 | GitHubRunnerShell: 25 | description: Shell for GitHubRunner jobs 26 | value: ${{ steps.readsettings.outputs.GitHubRunnerShell }} 27 | runs: 28 | using: composite 29 | steps: 30 | - name: run 31 | shell: ${{ inputs.shell }} 32 | id: readsettings 33 | env: 34 | _project: ${{ inputs.project }} 35 | _buildMode: ${{ inputs.buildMode }} 36 | _get: ${{ inputs.get }} 37 | run: | 38 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "ReadSettings" -Action { 39 | ${{ github.action_path }}/ReadSettings.ps1 -project $ENV:_project -buildMode $ENV:_buildMode -get $ENV:_get 40 | } 41 | branding: 42 | icon: terminal 43 | color: blue 44 | -------------------------------------------------------------------------------- /Actions/RunPSScriptAnalyzer/README.md: -------------------------------------------------------------------------------- 1 | # PowerShell Script Analyzer 2 | 3 | Run the PSScriptAnalyzer tool 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | pwsh | 16 | | path | Yes | Specifies the path to the scripts or module to be analyzed. Wildcard characters are supported. | .\\ | 17 | | excludeRule | | Comma separated list of PSScriptAnalyzer rules to exclude. Wildcard characters are supported. | | 18 | | recurse | | Runs Script Analyzer on the files in the Path directory and all subdirectories recursively. | | 19 | | output | Yes | Specifies where the path for the sarif file | results.sarif | 20 | 21 | ## OUTPUT 22 | 23 | ### ENV variables 24 | 25 | none 26 | 27 | ### OUTPUT variables 28 | 29 | none 30 | -------------------------------------------------------------------------------- /Actions/RunPSScriptAnalyzer/RunPSScriptAnalyzer.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string]$Path, 3 | [string[]]$ExcludeRule, 4 | [switch]$Recurse, 5 | [string]$Output 6 | ) 7 | 8 | $analyzerModule = Get-Module -ListAvailable -Name PSScriptAnalyzer 9 | if ($null -eq $analyzerModule) { 10 | Install-Module -Name PSScriptAnalyzer -Force 11 | } 12 | 13 | $sarifModule = Get-Module -ListAvailable -Name ConvertToSARIF 14 | if ($null -eq $sarifModule) { 15 | Install-Module -Name ConvertToSARIF -Force 16 | } 17 | Import-Module -Name ConvertToSARIF -Force 18 | 19 | $htPSA = [ordered]@{ Path = $Path } 20 | if ($ExcludeRule) { 21 | Write-Host "Excluding rules: $ExcludeRule" 22 | $htPSA.add('ExcludeRule', $ExcludeRule) 23 | } 24 | if ($Recurse) { 25 | Write-Host "Recurse: $Recurse" 26 | $htPSA.add('Recurse', $true) 27 | } 28 | $htCTS = [ordered]@{ FilePath = $Output } 29 | 30 | $maxRetries = 3 31 | $retryCount = 0 32 | $success = $false 33 | 34 | Write-Output "Modules installed, now running tests." 35 | while (-not $success -and $retryCount -lt $maxRetries) { 36 | Try { 37 | Invoke-ScriptAnalyzer @htPSA -Verbose | ConvertTo-SARIF @htCTS 38 | $success = $true 39 | } Catch { 40 | Write-Host "::Error:: $_" 41 | $retryCount++ 42 | Write-Output "Retrying... ($retryCount/$maxRetries)" 43 | } 44 | } 45 | 46 | if (-not $success) { 47 | Write-Host "::Error:: Failed after $maxRetries attempts." 48 | exit 1 49 | } 50 | -------------------------------------------------------------------------------- /Actions/RunPSScriptAnalyzer/action.yml: -------------------------------------------------------------------------------- 1 | name: Run PSScriptAnalyzer 2 | author: Microsoft Corporation 3 | branding: 4 | icon: "check" 5 | color: "gray-dark" 6 | inputs: 7 | shell: 8 | description: Shell in which you want to run the action (powershell or pwsh) 9 | required: false 10 | default: pwsh 11 | path: 12 | description: 'Specifies the path to the scripts or module to be analyzed. Wildcard characters are supported.' 13 | required: true 14 | default: '.\' 15 | excludeRule: 16 | description: 'Comma separated list of PSScriptAnalyzer rules to exclude. Wildcard characters are supported.' 17 | required: false 18 | recurse: 19 | description: 'Runs Script Analyzer on the files in the Path directory and all subdirectories recursively.' 20 | required: false 21 | output: 22 | description: 'Specifies where the path for the sarif file' 23 | required: true 24 | default: 'results.sarif' 25 | runs: 26 | using: "composite" 27 | steps: 28 | - name: run 29 | shell: ${{ inputs.shell }} 30 | id: RunPSScriptAnalyzer 31 | env: 32 | _path: ${{ inputs.path }} 33 | _excludeRule: ${{ inputs.excludeRule }} 34 | _recurse: ${{ inputs.recurse }} 35 | _output: ${{ inputs.output }} 36 | run: | 37 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "RunPSScriptAnalyzer" -Action { 38 | ${{ github.action_path }}/RunPSScriptAnalyzer.ps1 -path $ENV:_path -excludeRule @($ENV:_excludeRule -Replace ' ','' -Split ',') -Recurse:$($ENV:_recurse -eq 'true') -output $ENV:_output 39 | } 40 | -------------------------------------------------------------------------------- /Actions/RunPipeline/README.md: -------------------------------------------------------------------------------- 1 | # Run pipeline 2 | 3 | Run pipeline in AL-Go repository 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | | Secrets | env.Secrets with licenseFileUrl, codeSignCertificateUrl, codeSignCertificatePassword, keyVaultCertificateUrl, keyVaultCertificatePassword, keyVaultClientId, gitHubPackagesContext, applicationInsightsConnectionString must be read by a prior call to the ReadSecets Action | 13 | 14 | ### Parameters 15 | 16 | | Name | Required | Description | Default value | 17 | | :-- | :-: | :-- | :-- | 18 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 19 | | token | | The GitHub token running the action | github.token | 20 | | artifact | | ArtifactUrl to use for the build | settings.artifact | 21 | | project | | Project name if the repository is setup for multiple projects | . | 22 | | buildMode | | Specifies a mode to use for the build steps | Default | 23 | | installAppsJson | | A JSON-formatted list of apps to install | [] | 24 | | installTestAppsJson | | A JSON-formatted list of test apps to install | [] | 25 | | baselineWorkflowRunId | RunId of the baseline workflow run | | 26 | | baselineWorkflowSHA | SHA of the baseline workflow run | | 27 | 28 | ## OUTPUT 29 | 30 | ## ENV variables 31 | 32 | | Name | Description | 33 | | :-- | :-- | 34 | | containerName | Container name of a container used during build | 35 | 36 | ## OUTPUT variables 37 | 38 | none 39 | -------------------------------------------------------------------------------- /Actions/RunPipeline/action.yaml: -------------------------------------------------------------------------------- 1 | name: Run Pipeline 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The GitHub token running the action 10 | required: false 11 | default: ${{ github.token }} 12 | artifact: 13 | description: ArtifactUrl to use for the build 14 | required: false 15 | default: '' 16 | project: 17 | description: Project folder 18 | required: false 19 | default: '.' 20 | buildMode: 21 | description: Specifies a mode to use for the build steps 22 | required: false 23 | default: 'Default' 24 | installAppsJson: 25 | description: A JSON-formatted list of apps to install 26 | required: false 27 | default: '[]' 28 | installTestAppsJson: 29 | description: A JSON-formatted list of test apps to install 30 | required: false 31 | default: '[]' 32 | baselineWorkflowRunId: 33 | description: RunId of the baseline workflow run 34 | required: false 35 | default: '' 36 | baselineWorkflowSHA: 37 | description: SHA of the baseline workflow run 38 | required: false 39 | default: '' 40 | runs: 41 | using: composite 42 | steps: 43 | - name: run 44 | shell: ${{ inputs.shell }} 45 | env: 46 | _token: ${{ inputs.token }} 47 | _artifact: ${{ inputs.artifact }} 48 | _project: ${{ inputs.project }} 49 | _buildMode: ${{ inputs.buildMode }} 50 | _installAppsJson: ${{ inputs.installAppsJson }} 51 | _installTestAppsJson: ${{ inputs.installTestAppsJson }} 52 | _baselineWorkflowRunId: ${{ inputs.baselineWorkflowRunId }} 53 | _baselineWorkflowSHA: ${{ inputs.baselineWorkflowSHA }} 54 | run: | 55 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "RunPipeline" -Action { 56 | ${{ github.action_path }}/RunPipeline.ps1 -token $ENV:_token -artifact $ENV:_artifact -project $ENV:_project -buildMode $ENV:_buildMode -installAppsJson $ENV:_installAppsJson -installTestAppsJson $ENV:_installTestAppsJson -baselineWorkflowRunId $ENV:_baselineWorkflowRunId -baselineWorkflowSHA $ENV:_baselineWorkflowSHA 57 | } 58 | branding: 59 | icon: terminal 60 | color: blue 61 | -------------------------------------------------------------------------------- /Actions/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This GitHub repo is auto-generated from https://github.com/microsoft/AL-Go. Issues, bug tracking and feature requests should be done there. 6 | 7 | Please follow the documentation [here](https://github.com/microsoft/AL-Go/blob/main/Scenarios/Contribute.md) if you want to contribute to AL-Go for GitHub. 8 | 9 | ## Microsoft Support Policy 10 | 11 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 12 | -------------------------------------------------------------------------------- /Actions/SetActionsRepoAndRef.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "Actions Repository", Mandatory = $true)] 3 | [string] $actionsRepo, 4 | [Parameter(HelpMessage = "Actions Ref", Mandatory = $true)] 5 | [string] $actionsRef 6 | ) 7 | 8 | $ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 9 | 10 | Write-Host "Current action repository: $actionsRepo" 11 | Write-Host "Current action ref: $actionsRef" 12 | 13 | # Set the path where the actions will be checked out 14 | # Default path is ./_AL-Go/Actions 15 | $actionsPath = './_AL-Go/Actions' 16 | if ($actionsRepo -like '*/AL-Go') { # direct development 17 | # Set the path one level up as that where the Actions folder will be 18 | $actionsPath = './_AL-Go' 19 | } 20 | Add-Content -encoding utf8 -Path $env:GITHUB_ENV -Value "actionsRepo=$actionsRepo" 21 | Add-Content -encoding utf8 -Path $env:GITHUB_ENV -Value "actionsRef=$actionsRef" 22 | Add-Content -encoding utf8 -Path $env:GITHUB_ENV -Value "actionsPath=$actionsPath" 23 | -------------------------------------------------------------------------------- /Actions/Sign/README.md: -------------------------------------------------------------------------------- 1 | # Sign 2 | 3 | Sign apps with a certificate stored in Azure Key Vault 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | | Name | Description | 10 | | :-- | :-- | 11 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 12 | 13 | ### Parameters 14 | 15 | | Name | Required | Description | Default value | 16 | | :-- | :-: | :-- | :-- | 17 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 18 | | azureCredentialsJson | Yes | Azure Credentials secret (Base 64 encoded) | | 19 | | timestampService | | The URI of the timestamp server | http://timestamp.digicert.com | 20 | | digestAlgorithm | | The digest algorithm to use for signing and timestamping | SHA256 | 21 | | pathToFiles | Yes | The path to the files to be signed | 22 | 23 | ## OUTPUT 24 | 25 | none 26 | -------------------------------------------------------------------------------- /Actions/Sign/action.yaml: -------------------------------------------------------------------------------- 1 | name: Sign 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | azureCredentialsJson: 9 | description: Azure Credentials secret (Base 64 encoded) 10 | required: true 11 | pathToFiles: 12 | description: The path to the files to be signed 13 | required: true 14 | timestampService: 15 | description: The URI of the timestamp server 16 | required: false 17 | default: http://timestamp.digicert.com 18 | digestAlgorithm: 19 | description: The digest algorithm to use for signing and timestamping 20 | required: false 21 | default: SHA256 22 | runs: 23 | using: composite 24 | steps: 25 | - name: run 26 | shell: ${{ inputs.shell }} 27 | env: 28 | _azureCredentialsJson: ${{ inputs.azureCredentialsJson }} 29 | _pathToFiles: ${{ inputs.pathToFiles }} 30 | _timestampService: ${{ inputs.timestampService }} 31 | _digestAlgorithm: ${{ inputs.digestAlgorithm }} 32 | run: | 33 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "Sign" -Action { 34 | ${{ github.action_path }}/Sign.ps1 -AzureCredentialsJson $ENV:_azureCredentialsJson -PathToFiles $ENV:_pathToFiles -TimestampService $ENV:_timestampService -digestAlgorithm $ENV:_digestAlgorithm 35 | } 36 | branding: 37 | icon: terminal 38 | color: blue 39 | -------------------------------------------------------------------------------- /Actions/Troubleshooting/README.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | Run troubleshooting on repository 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | gitHubSecrets | Yes | GitHub secrets in a json structure | | 17 | | displayNameOfSecrets | Yes | Display the names (not the values) of secrets available to the repository | | 18 | 19 | ## OUTPUT 20 | 21 | none 22 | -------------------------------------------------------------------------------- /Actions/Troubleshooting/action.yaml: -------------------------------------------------------------------------------- 1 | name: Troubleshooting 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | gitHubSecrets: 9 | description: All GitHub Secrets in compressed JSON format 10 | required: true 11 | displayNameOfSecrets: 12 | description: Display the name (not the value) of secrets available to the repository 13 | required: true 14 | runs: 15 | using: composite 16 | steps: 17 | - name: run 18 | shell: ${{ inputs.shell }} 19 | env: 20 | _displayNameOfSecrets: ${{ inputs.displayNameOfSecrets }} 21 | run: | 22 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "Troubleshooting" -Action { 23 | ${{ github.action_path }}/Troubleshooting.ps1 -gitHubSecrets '${{ inputs.gitHubSecrets }}' -displayNameOfSecrets ($ENV:_displayNameOfSecrets -eq 'true') 24 | } 25 | branding: 26 | icon: terminal 27 | color: blue 28 | -------------------------------------------------------------------------------- /Actions/ValidateWorkflowInput/README.md: -------------------------------------------------------------------------------- 1 | # Validate Workflow Input 2 | 3 | Validate Workflow Input 4 | 5 | ## INPUT 6 | 7 | Validation script for calling workflow must exist 8 | 9 | ### ENV variables 10 | 11 | | Name | Description | 12 | | :-- | :-- | 13 | | Settings | env.Settings must be set by a prior call to the ReadSettings Action | 14 | 15 | ### Parameters 16 | 17 | | Name | Required | Description | Default value | 18 | | :-- | :-: | :-- | :-- | 19 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 20 | 21 | ## OUTPUT 22 | 23 | throws if validation script doesn't exist or any validated fields are invalid 24 | -------------------------------------------------------------------------------- /Actions/ValidateWorkflowInput/Validate-createrelease.ps1: -------------------------------------------------------------------------------- 1 | # Validate the inputs for the create release workflow 2 | Param( 3 | [Parameter(Mandatory=$true)] 4 | [hashtable] $settings, 5 | 6 | [Parameter(Mandatory=$true)] 7 | [PSCustomObject] $eventPath 8 | ) 9 | 10 | foreach($inputname in $eventPath.inputs.PSObject.Properties.Name) { 11 | $inputValue = $eventPath.inputs."$inputName" 12 | switch ($inputName) { 13 | 'UpdateVersionNumber' { 14 | Validate-UpdateVersionNumber -settings $settings -inputName $inputName -inputValue $inputValue 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Actions/ValidateWorkflowInput/Validate-incrementversionnumber.ps1: -------------------------------------------------------------------------------- 1 | # Validate the inputs for the increment version workflow 2 | Param( 3 | [Parameter(Mandatory=$true)] 4 | [hashtable] $settings, 5 | 6 | [Parameter(Mandatory=$true)] 7 | [PSCustomObject] $eventPath 8 | ) 9 | 10 | foreach($inputname in $eventPath.inputs.PSObject.Properties.Name) { 11 | $inputValue = $eventPath.inputs."$inputName" 12 | switch ($inputName) { 13 | 'VersionNumber' { 14 | Validate-UpdateVersionNumber -settings $settings -inputName $inputName -inputValue $inputValue 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Actions/ValidateWorkflowInput/ValidateWorkflowInput.ps1: -------------------------------------------------------------------------------- 1 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 2 | Import-Module (Join-Path -Path $PSScriptRoot -ChildPath "ValidateWorkflowInput.psm1" -Resolve) -Force -DisableNameChecking 3 | 4 | $workflowName = "$ENV:GITHUB_WORKFLOW".Trim().Replace(' ','').ToLowerInvariant().Split([System.IO.Path]::getInvalidFileNameChars()) -join "" 5 | $ValidateWorkflowScript = Join-Path -Path $PSScriptRoot -ChildPath "Validate-$workflowName.ps1" 6 | 7 | # If a workflow references this action, there must be a validate script for it 8 | if (-not (Test-Path -Path $ValidateWorkflowScript)) { 9 | throw "No validate workflow script found for $workflowName." 10 | } 11 | 12 | $settings = $env:Settings | ConvertFrom-Json | ConvertTo-HashTable 13 | $eventPath = Get-Content -Encoding UTF8 -Path $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json 14 | 15 | # If a workflow references this action, it must have inputs 16 | if ($null -eq $eventPath.inputs) { 17 | throw "No inputs found in $env:GITHUB_EVENT_PATH" 18 | } 19 | 20 | # Validate the inputs for the workflow - there doesn't have to be validators for all inputs 21 | . $ValidateWorkflowScript -settings $settings -eventPath $eventPath 22 | -------------------------------------------------------------------------------- /Actions/ValidateWorkflowInput/ValidateWorkflowInput.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | This module contains functions to validate input values for the workflow. 4 | The functions are called from the workflow to validate the inputs. 5 | #> 6 | 7 | 8 | <# 9 | Validates the version number input for the workflow. 10 | The version number must be a valid version number or a relative version number. 11 | The version number can have 2 or 3 segments, depending on the versioning strategy. 12 | The function checks if the version number is in the correct format and throws an error if it is not. 13 | #> 14 | function Validate-UpdateVersionNumber { 15 | [CmdletBinding()] 16 | Param( 17 | [Parameter(Mandatory = $true)] 18 | [hashtable] $settings, 19 | [Parameter(Mandatory = $true)] 20 | [string] $inputName, 21 | [Parameter(Mandatory = $true)] 22 | [string] $inputValue 23 | ) 24 | 25 | $strategy3 = (($settings.versioningStrategy -band 15) -eq 3) 26 | $legalRelativeValues = @('+1','+0.1') 27 | if ($strategy3) { 28 | $legalRelativeValues += @('+0.0.1') 29 | } 30 | $errorMessage = "$inputName is '$inputValue', must be a version number with $(2+[int]$strategy3) segments or one of: $($legalRelativeValues -join ', ')" 31 | if ($inputValue.StartsWith('+')) { 32 | # Relative version number 33 | if ($legalRelativeValues -notcontains $inputValue) { 34 | throw $errorMessage 35 | } 36 | } 37 | else { 38 | # Absolute version number 39 | try { 40 | $versionNumber = [System.Version]::Parse($inputValue) 41 | } 42 | catch { 43 | throw $errorMessage 44 | } 45 | if (($versionNumber.Revision -ne -1) -or (!$strategy3 -and ($versionNumber.Build -ne -1))) { 46 | throw $errorMessage 47 | } 48 | if ($strategy3 -and $versionNumber.Build -eq -1) { 49 | throw $errorMessage 50 | } 51 | } 52 | } 53 | 54 | Export-ModuleMember *-* 55 | -------------------------------------------------------------------------------- /Actions/ValidateWorkflowInput/action.yaml: -------------------------------------------------------------------------------- 1 | name: Validate Workflow Input 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | runs: 9 | using: composite 10 | steps: 11 | - name: run 12 | shell: ${{ inputs.shell }} 13 | run: | 14 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "ValidateWorkflowInput" -Action { 15 | ${{ github.action_path }}/ValidateWorkflowInput.ps1 16 | } 17 | branding: 18 | icon: terminal 19 | color: blue 20 | -------------------------------------------------------------------------------- /Actions/VerifyPRChanges/README.md: -------------------------------------------------------------------------------- 1 | # Verify Pull Request changes 2 | 3 | Verify Pull Request Changes for AL-Go workflows 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | token | | The token to use for the GitHub API |github.token | 17 | | prBaseRepository | | The name of the repository the PR is going to | github.event.pull_request.base.repo.full_name | 18 | | pullRequestId | | The id of the pull request | github.event.pull_request.number | 19 | 20 | ## OUTPUT 21 | 22 | none 23 | -------------------------------------------------------------------------------- /Actions/VerifyPRChanges/action.yaml: -------------------------------------------------------------------------------- 1 | name: Verify PR Changes 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | token: 9 | description: The token to use for the GitHub API 10 | required: false 11 | default: ${{ github.token }} 12 | prBaseRepository: 13 | description: The name of the repository the PR is going to 14 | required: false 15 | default: ${{ github.event.pull_request.base.repo.full_name }} 16 | pullRequestId: 17 | description: The id of the pull request 18 | required: false 19 | default: ${{ github.event.pull_request.number }} 20 | runs: 21 | using: composite 22 | steps: 23 | - name: run 24 | shell: ${{ inputs.shell }} 25 | env: 26 | _token: ${{ inputs.token }} 27 | _prBaseRepository: ${{ inputs.prBaseRepository }} 28 | _pullRequestId: ${{ inputs.pullRequestId }} 29 | run: | 30 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "VerifyPRChanges" -Action { 31 | ${{ github.action_path }}/VerifyPRChanges.ps1 -token $ENV:_token -prBaseRepository $ENV:_prBaseRepository -pullRequestId $ENV:_pullRequestId 32 | } 33 | branding: 34 | icon: terminal 35 | color: blue 36 | -------------------------------------------------------------------------------- /Actions/WorkflowInitialize/README.md: -------------------------------------------------------------------------------- 1 | # Initialize workflow 2 | 3 | Initialize a workflow 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | actionsRepo | No | The repository of the action | github.action_repository | 17 | | actionsRef | No | The ref of the action | github.action_ref | 18 | 19 | ## OUTPUT 20 | 21 | ### ENV variables 22 | 23 | none 24 | 25 | ### OUTPUT variables 26 | 27 | | Name | Description | 28 | | :-- | :-- | 29 | | telemetryScopeJson | A telemetryScope that covers the workflow | 30 | -------------------------------------------------------------------------------- /Actions/WorkflowInitialize/WorkflowInitialize.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(HelpMessage = "The repository of the action", Mandatory = $false)] 3 | [string] $actionsRepo, 4 | [Parameter(HelpMessage = "The ref of the action", Mandatory = $false)] 5 | [string] $actionsRef 6 | ) 7 | 8 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve) 9 | . (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-TestRepoHelper.ps1" -Resolve) 10 | 11 | if ($actionsRepo -eq 'microsoft/AL-Go-Actions') { 12 | Write-Host "Using AL-Go for GitHub $actionsRef" 13 | $verstr = $actionsRef 14 | } 15 | elseif ($actionsRepo -eq 'microsoft/AL-Go') { 16 | Write-Host "Using AL-Go for GitHub Preview ($actionsRef)" 17 | $verstr = "p" 18 | } 19 | else { 20 | Write-Host "Using direct AL-Go development ($($actionsRepo)@$actionsRef)" 21 | $verstr = "d" 22 | } 23 | 24 | Write-Big -str "a$verstr" 25 | 26 | # Test the AL-Go repository is set up correctly 27 | TestALGoRepository 28 | 29 | # Test the prerequisites for the test runner 30 | TestRunnerPrerequisites 31 | 32 | # Create a json object that contains an entry for the workflowstarttime 33 | $scopeJson = @{ 34 | "workflowStartTime" = [DateTime]::UtcNow 35 | } | ConvertTo-Json -Compress 36 | 37 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "telemetryScopeJson=$scopeJson" 38 | -------------------------------------------------------------------------------- /Actions/WorkflowInitialize/action.yaml: -------------------------------------------------------------------------------- 1 | name: Workflow Initialize 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | actionsRepo: 9 | description: The repository of the action 10 | required: false 11 | default: ${{ github.action_repository }} 12 | actionsRef: 13 | description: The ref of the action 14 | required: false 15 | default: ${{ github.action_ref }} 16 | outputs: 17 | telemetryScopeJson: 18 | description: A telemetryScope that covers the workflow 19 | value: ${{ steps.workflowinitialize.outputs.telemetryScopeJson }} 20 | runs: 21 | using: composite 22 | steps: 23 | - name: run 24 | shell: ${{ inputs.shell }} 25 | id: workflowinitialize 26 | env: 27 | _actionsRepo: ${{ inputs.actionsRepo }} 28 | _actionsRef: ${{ inputs.actionsRef }} 29 | run: | 30 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "WorkflowInitialize" -Action { 31 | ${{ github.action_path }}/WorkflowInitialize.ps1 -actionsRepo $ENV:_actionsRepo -actionsRef $ENV:_actionsRef 32 | } 33 | branding: 34 | icon: terminal 35 | color: blue 36 | -------------------------------------------------------------------------------- /Actions/WorkflowPostProcess/README.md: -------------------------------------------------------------------------------- 1 | # PostProcess action 2 | 3 | Finalize a workflow 4 | 5 | ## INPUT 6 | 7 | ### ENV variables 8 | 9 | none 10 | 11 | ### Parameters 12 | 13 | | Name | Required | Description | Default value | 14 | | :-- | :-: | :-- | :-- | 15 | | shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell | 16 | | telemetryScopeJson | | Telemetry scope generated during the workflow initialization | {} | 17 | | currentJobContext | | The current job context | '' | 18 | | actionsRepo | No | The repository of the action | github.action_repository | 19 | | actionsRef | No | The ref of the action | github.action_ref | 20 | 21 | ## OUTPUT 22 | 23 | none 24 | -------------------------------------------------------------------------------- /Actions/WorkflowPostProcess/action.yaml: -------------------------------------------------------------------------------- 1 | name: Workflow Post Process 2 | author: Microsoft Corporation 3 | inputs: 4 | shell: 5 | description: Shell in which you want to run the action (powershell or pwsh) 6 | required: false 7 | default: powershell 8 | telemetryScopeJson: 9 | description: Telemetry scope generated during the workflow initialization 10 | required: false 11 | default: '7b7d' 12 | currentJobContext: 13 | description: The current job context 14 | required: false 15 | default: '' 16 | actionsRepo: 17 | description: The repository of the action 18 | required: false 19 | default: ${{ github.action_repository }} 20 | actionsRef: 21 | description: The ref of the action 22 | required: false 23 | default: ${{ github.action_ref }} 24 | runs: 25 | using: composite 26 | steps: 27 | - name: run 28 | shell: ${{ inputs.shell }} 29 | env: 30 | _telemetryScopeJson: ${{ inputs.telemetryScopeJson }} 31 | _currentJobContext: ${{ inputs.currentJobContext }} 32 | _actionsRepo: ${{ inputs.actionsRepo }} 33 | _actionsRef: ${{ inputs.actionsRef }} 34 | run: | 35 | ${{ github.action_path }}/../Invoke-AlGoAction.ps1 -ActionName "WorkflowPostProcess" -Action { 36 | ${{ github.action_path }}/WorkflowPostProcess.ps1 -telemetryScopeJson $ENV:_telemetryScopeJson -currentJobContext $ENV:_currentJobContext -actionsRepo $ENV:_actionsRepo -actionsRef $ENV:_actionsRef 37 | } 38 | branding: 39 | icon: terminal 40 | color: blue 41 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo. 2 | * @microsoft/d365-bc-engineering-systems 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /Internal/Overrides/1st party apps/NewBcContainer.ps1: -------------------------------------------------------------------------------- 1 |  2 | Param( 3 | [Hashtable]$parameters 4 | ) 5 | 6 | New-BcContainer @parameters 7 | 8 | Get-Location | Out-Host 9 | Write-Host "Removing companies" 10 | $keepCompany = "CRONUS Danmark A/S" 11 | Get-CompanyInBcContainer -containerName $parameters.ContainerName | Where-Object { $_.CompanyName -ne $keepCompany } | ForEach-Object { 12 | Remove-CompanyInBcContainer -containerName $parameters.ContainerName -companyName $_.CompanyName 13 | } 14 | Clean-BcContainerDatabase ` 15 | -containerName $parameters.ContainerName ` 16 | -credential $parameters.credential ` 17 | -saveData ` 18 | -onlySaveBaseAppData ` 19 | -keepBaseApp 20 | 21 | Invoke-ScriptInBcContainer -containerName $parameters.ContainerName -scriptblock { $progressPreference = 'SilentlyContinue' } 22 | -------------------------------------------------------------------------------- /Internal/Overrides/System Application/NewBcContainer.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Hashtable]$parameters 3 | ) 4 | 5 | New-BcContainer @parameters 6 | 7 | $installedApps = Get-BcContainerAppInfo -containerName $containerName -tenantSpecificProperties -sort DependenciesLast 8 | $installedApps | % { 9 | Write-Host "Removing $($_.Name)" 10 | Unpublish-BcContainerApp -containerName $parameters.ContainerName -name $_.Name -unInstall -doNotSaveData -doNotSaveSchema -force 11 | } 12 | 13 | Invoke-ScriptInBcContainer -containerName $parameters.ContainerName -scriptblock { $progressPreference = 'SilentlyContinue' } 14 | -------------------------------------------------------------------------------- /Internal/Scripts/GetOwnerForE2ETests.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory=$false, HelpMessage="The GitHub owner from the input.")] 3 | [string]$githubOwner 4 | ) 5 | 6 | $ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 7 | 8 | if (!($githubOwner)) { 9 | $githubOwner = "$ENV:GITHUB_REPOSITORY_OWNER" 10 | } 11 | 12 | $orgmap = Get-Content -Path (Join-Path "." "e2eTests/orgmap.json") -Encoding UTF8 -Raw | ConvertFrom-Json 13 | if ($orgmap.PSObject.Properties.Name -eq $githubOwner) { 14 | $githubOwner = $orgmap."$githubOwner" 15 | } 16 | 17 | Write-Host "githubOwner=$githubOwner" 18 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "githubOwner=$githubOwner" 19 | -------------------------------------------------------------------------------- /Internal/Scripts/RemoveTempRepos.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true, HelpMessage="The GitHub owner of the repositories to remove.")] 3 | [string] $githubOwner 4 | ) 5 | 6 | $ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 7 | Import-Module (Join-Path "." "e2eTests/e2eTestHelper.psm1") -DisableNameChecking 8 | 9 | @(invoke-gh repo list $githubOwner --limit 1000 -silent -returnValue) | ForEach-Object { $_.Split("`t")[0] } | Where-Object { "$_" -like "$githubOwner/tmp*" } | ForEach-Object { 10 | $repo = $_ 11 | Write-Host "https://github.com/$repo" 12 | $repoOwner = $repo.Split('/')[0] 13 | @((invoke-gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "/orgs/$repoOwner/packages?package_type=nuget" -silent -returnvalue -ErrorAction SilentlyContinue | ConvertFrom-Json)) | Where-Object { ($_.PSObject.Properties.Name -eq 'repository') -and ($_.repository.full_name -eq $repo) } | ForEach-Object { 14 | Write-Host "- package $($_.name)" 15 | # Pipe empty string into GH API --METHOD DELETE due to https://github.com/cli/cli/issues/3937 16 | '' | invoke-gh api --method DELETE -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "/orgs/$repoOwner/packages/nuget/$($_.name)" --input - 17 | } 18 | invoke-gh repo delete "https://github.com/$repo" --yes | Out-Host 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 7 | feature request as a new Issue. 8 | 9 | ## Microsoft Support Policy 10 | 11 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 12 | -------------------------------------------------------------------------------- /Scenarios/AppDependencies.md: -------------------------------------------------------------------------------- 1 | # Introducing a dependency to an app on GitHub 2 | 3 | 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. 4 | 5 | The `appDependencyProbingPaths` key in the settings expects a json array with the following structure: 6 | 7 | ```json 8 | "appDependencyProbingPaths": [ 9 | { 10 | "repo": "https://github.com//", 11 | "version": "", 12 | "release_status": "", 13 | "authTokenSecret": "", 14 | "projects": "*" 15 | } 16 | ] 17 | ``` 18 | 19 | **repo** specifies the URL of the foreign repository. 20 | 21 | **version** specifies the version of the dependency to be downloaded it could be set to **latest** or a specific version. 22 | 23 | **release_status** specifies the type of release on the foreign repository. The artifacts can be downloaded from a release, prerelease, or a draft. 24 | 25 | **authTokenSecret** If the foreign repository is private, to download the artifacts an access token is needed. In this case a secret should be added to GitHub secrets or Azure Key vault and the name of the secret should be provided in the settings. 26 | 27 | **projects** specifies the project in a multi project repository. “\*” means all projects. 28 | 29 | ______________________________________________________________________ 30 | 31 | [back](../README.md) 32 | -------------------------------------------------------------------------------- /Scenarios/CreateOnlineDevEnv.md: -------------------------------------------------------------------------------- 1 | # Create Online Development Environment from VS Code 2 | 3 | *Prerequisites: A completed [scenario 7](UseAzureKeyVault.md)* 4 | 5 | 1. Open your **App1** project in VS Code, open the **cloudDevEnv.ps1** in your **.AL-Go** folder and run the script. 6 | ![Cloud DevEnv](https://github.com/microsoft/AL-Go/assets/10775043/adfafea6-4136-4120-95e7-45e7313cc67d) 7 | 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. 8 | ![Cloud DevEnv](https://github.com/microsoft/AL-Go/assets/10775043/ce042a0a-0a91-481f-8752-4fa40ec78424) 9 | 1. Open [https://aka.ms/devicelogin](https://aka.ms/devicelogin) and paste in the **code provided**, sign in and accept that you are trying to sign in with PowerShell. 10 | ![Cloud DevEnv](https://github.com/microsoft/AL-Go/assets/10775043/751bb507-1a5e-436f-8a2a-1acdd53c33ab) 11 | 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** 12 | ![Cloud DevEnv](https://github.com/microsoft/AL-Go/assets/10775043/20c5848a-3238-4fed-a1f2-36dd027884cd) 13 | 1. Modify your app, press **F5** and select the **Cloud Sandbox** with your new name. 14 | ![Cloud DevEnv](https://github.com/microsoft/AL-Go/assets/10775043/7cebf477-28ff-4746-9004-c5075015b7c8) 15 | 1. Your online environment will have your app changes. 16 | ![Cloud DevEnv](https://github.com/microsoft/AL-Go/assets/10775043/6c5b5ebd-c46e-41e6-bc5e-e25344ecb3ae) 17 | 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. 18 | 19 | ______________________________________________________________________ 20 | 21 | [back](../README.md) 22 | -------------------------------------------------------------------------------- /Scenarios/EnableKeyVaultForAppSourceApp.md: -------------------------------------------------------------------------------- 1 | # Enable KeyVault access for your AppSource App during development and/or tests 2 | 3 | For AppSource apps, if you want to enable KeyVault access for your app (as described [here](https://go.microsoft.com/fwlink/?linkid=2217058&clcid=0x409) you can add the access to this keyvault in your local development environment or your pipelines (for running tests) by adding 3 secrets to either the GitHub repo or your KeyVault. Based on [this walkthrough](https://go.microsoft.com/fwlink/?linkid=2216856&clcid=0x409) you will need to create 3 secrets: 4 | 5 | - A **KeyVaultClientId**, which is the Client ID for the Microsoft Entra application registration with access to the KeyVault. 6 | - A **KeyVaultCertificateUrl**, pointing to a certificate which gives you access to the Microsoft Entra application registration. 7 | - A **KeyVaultCertificatePassword**, which is the password for this certificate. 8 | 9 | In the case of KeyVault access for apps, it is not enough to just add the secrets, you will also have to add information in the **.AL-Go\\settings.json** that this app uses this KeyVault. Add these three settings 10 | 11 | ```json 12 | "KeyVaultCertificateUrlSecretName": "KeyVaultCertificateUrl", 13 | "KeyVaultCertificatePasswordSecretName": "KeyVaultCertificatePassword", 14 | "KeyVaultClientIdSecretName": "KeyVaultClientId", 15 | ``` 16 | 17 | With this, containers set up for build pipelines or development environments will have access to this keyvault. 18 | 19 | ______________________________________________________________________ 20 | 21 | [back](../README.md) 22 | -------------------------------------------------------------------------------- /Scenarios/RegisterProductionEnvironment.md: -------------------------------------------------------------------------------- 1 | # Register a customer production environment for Manual Deployment 2 | 3 | *Prerequisites: A completed ["Create a release of your application"](CreateRelease.md) scenario, an online production environment setup for S2S as specified in task 2 here: [Using Service to Service Authentication - Business Central | Microsoft Docs](https://go.microsoft.com/fwlink/?linkid=2217415&clcid=0x409), using the same Microsoft Entra application registration as scenario 3* 4 | 5 | > [!NOTE] 6 | > For access to environments, environment secrets, and deployment branches in private or internal repositories, you must use GitHub Pro, GitHub Team, or GitHub Enterprise. (see [this](https://go.microsoft.com/fwlink/?linkid=2216857&clcid=0x409)). We are considering adding a secondary option for listing environments. 7 | 8 | 1. Following the process in step 3, you can add an environment to the GitHub repository under settings called **MYPROD (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**. 9 | 10 | ![Publish to MYPROD](https://github.com/user-attachments/assets/fdb05510-2785-483a-b2f3-98a2fe36bfc4) 11 | 12 | 1. When running the **Publish to Environment** workflow, you should see that the app is deployed to the **MYPROD** environment only. 13 | 14 | ![MYPROD](https://github.com/user-attachments/assets/04dab8af-57b4-4bc3-a0c2-6e6869d8df34) 15 | 16 | > [!NOTE] 17 | > If your Business Central environment name contains spaces or special characters, you might need to map your GitHub environment name to your Business Central environment name using the DeployTo setting with an EnvironmentName setting called DeployTo. 18 | 19 | ```json 20 | "DeployTo": { 21 | "EnvironmentName": "" 22 | } 23 | ``` 24 | 25 | ______________________________________________________________________ 26 | 27 | [back](../README.md) 28 | -------------------------------------------------------------------------------- /Scenarios/SetupCiCdForExistingPTE.md: -------------------------------------------------------------------------------- 1 | # Set up CI/CD for an existing per-tenant extension (BingMaps) 2 | 3 | *Prerequisites: A GitHub account. We will use the BingMaps sample app, which can be found on GitHub in the [Business Central BingMaps.PTE repo](https://github.com/microsoft/bcsamples-bingmaps.pte). Copy the URL to the **bcsamples-bingmaps.pte-main-Apps** artifact of the latest release to the clipboard from here: [https://github.com/microsoft/bcsamples-bingmaps.pte/releases](https://github.com/microsoft/bcsamples-bingmaps.pte/releases) – you can also download the .zip file and see the content of it.* 4 | 5 | 1. Navigate to [https://github.com/microsoft/AL-Go-PTE](https://github.com/microsoft/AL-Go-PTE) and then choose **Use this template**. 6 | 7 | ![Use this template](https://github.com/microsoft/AL-Go/assets/10775043/b4e32467-723d-434e-8c0a-45c6254699b4) 8 | 9 | 1. Enter **app2** as repository name and select **Create Repository from template**. 10 | 11 | 1. Under **Actions** select the **Add existing app or test app** workflow and choose **Run workflow**. 12 | 13 | 1. In the **Direct Download URL** field, paste in the direct download URL of the BingMaps sample from above. 14 | 15 | 1. When the workflow is complete, inspect the **Pull request**. 16 | 17 | ![Pull Request](https://github.com/microsoft/AL-Go/assets/10775043/a02cdef9-b3f7-486a-be32-a19a3f56525d) 18 | 19 | 1. Merge the pull request. The **CI/CD** workflow will kick off. 20 | 21 | ![CI/CD](https://github.com/microsoft/AL-Go/assets/10775043/58ab0a72-4b81-4a52-814f-a0984d7154de) 22 | 23 | 1. After the workflow completes, you can investigate the output and see that everything works. 24 | 25 | ![Success](https://github.com/microsoft/AL-Go/assets/10775043/d7806af4-822d-43ea-8103-dd7c69e8fd64) 26 | 27 | 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. 28 | 29 | ______________________________________________________________________ 30 | 31 | [back](../README.md) 32 | -------------------------------------------------------------------------------- /Scenarios/SetupServicePrincipalForPowerPlatform.md: -------------------------------------------------------------------------------- 1 | # How to set up Service Principal for Power Platform 2 | 3 | Setting up a service principal can be done in 2 steps: setting up the principal and adding appropriate roles to the Power Platform environment. 4 | 5 | 1. In Azure AD, create the service principal. 6 | 7 | To create a service principal, you'll have to register an app with Azure AD and set it up for password-based authentication (with a client secret). 8 | 9 | You can do this step using the Azure portal or PowerShell. For more information, see one the following articles: 10 | 11 | - [Create an Azure AD application and service principal (using Azure portal)](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal) 12 | - [Create service principal and client secret using PowerShell](https://learn.microsoft.com/en-us/power-platform/alm/devops-build-tools#create-service-principal-and-client-secret-using-powershell) 13 | 14 |
15 | 16 | 2. In Power Platform, add the service principal as an app user on the environment. 17 | 18 | Using Power Platform admin center, add the service principal as an application user of the environment and assign it either the **System admin** or **Super** role. **System admin** is recommended. 19 | 20 | For more information, see [Manage app users in Power Platform](https://learn.microsoft.com/en-us/power-platform/admin/manage-application-users). 21 | -------------------------------------------------------------------------------- /Scenarios/UseAzureKeyVault.md: -------------------------------------------------------------------------------- 1 | # Use Azure KeyVault for secrets with AL-Go 2 | 3 | *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://learn.microsoft.com/azure/developer/github/connect-from-azure?tabs=azure-portal%2Cwindows#use-the-azure-login-action-with-a-service-principal-secret). Add your KeyVault name to the the JSON construct from this walkthrough (using **“keyVaultName” : “{your keyvault name}”**) and add this compressed 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 want to mess with the JSON construct.* 4 | 5 | *If you need to use Hardware Security Modules, you'll need to use a Premium SKU key vault. For more information on this, see [learn.microsoft.com](https://learn.microsoft.com/en-us/azure/key-vault/keys/about-keys)* 6 | 7 | *Please note that the name specified in the app registration should use a verified domain of the organization (f.ex. the login from your office 365 account) and could be https://myapp.mydomainname.com)* 8 | 9 | 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. 10 | 1. Run the CI/CD pipeline to see that the deployment still works, reading the **authContext** secret from the KeyVault. 11 | ![runpipeline](https://github.com/microsoft/AL-Go/assets/10775043/0dd31eb9-e135-46e3-a526-d47873f08b63) 12 | 1. Redo scenario 6 to see that Update AL-Go System files still works. 13 | 14 | ______________________________________________________________________ 15 | 16 | [back](../README.md) 17 | -------------------------------------------------------------------------------- /Scenarios/images/branchingstrategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AL-Go/405966b5782867ad1d533cf2e6ba0bf5cd6b26b1/Scenarios/images/branchingstrategy.png -------------------------------------------------------------------------------- /Templates/AppSource App/.AL-Go/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "country": "us", 4 | "appSourceCopMandatoryAffixes": [ 5 | "" 6 | ], 7 | "appFolders": [], 8 | "testFolders": [], 9 | "bcptTestFolders": [] 10 | } 11 | -------------------------------------------------------------------------------- /Templates/AppSource App/.github/AL-Go-Settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "type": "AppSource App", 4 | "templateUrl": "https://github.com/microsoft/AL-Go-AppSource@main" 5 | } 6 | -------------------------------------------------------------------------------- /Templates/AppSource App/.github/Test Current.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "artifact": "////latest", 4 | "cacheImageName": "", 5 | "versioningStrategy": 15 6 | } 7 | -------------------------------------------------------------------------------- /Templates/AppSource App/.github/Test Next Major.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "artifact": "////nextmajor", 4 | "cacheImageName": "", 5 | "versioningStrategy": 15 6 | } 7 | -------------------------------------------------------------------------------- /Templates/AppSource App/.github/Test Next Minor.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "artifact": "////nextminor", 4 | "cacheImageName": "", 5 | "versioningStrategy": 15 6 | } 7 | -------------------------------------------------------------------------------- /Templates/AppSource App/.github/workflows/Troubleshooting.yaml: -------------------------------------------------------------------------------- 1 | name: 'Troubleshooting' 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | displayNameOfSecrets: 7 | description: Display the name (not the value) of secrets available to the repository 8 | type: boolean 9 | default: false 10 | 11 | permissions: 12 | actions: read 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | shell: powershell 18 | 19 | env: 20 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 21 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 22 | 23 | jobs: 24 | Troubleshooting: 25 | runs-on: [ windows-latest ] 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | with: 30 | lfs: true 31 | 32 | - name: Troubleshooting 33 | uses: microsoft/AL-Go-Actions/Troubleshooting@main 34 | with: 35 | shell: powershell 36 | gitHubSecrets: ${{ toJson(secrets) }} 37 | displayNameOfSecrets: ${{ github.event.inputs.displayNameOfSecrets }} 38 | -------------------------------------------------------------------------------- /Templates/AppSource App/.gitignore: -------------------------------------------------------------------------------- 1 | *.app 2 | *.flf 3 | *.bclicense 4 | *.g.xlf 5 | .DS_Store 6 | Thumbs.db 7 | TestResults*.xml 8 | bcptTestResults*.json 9 | BuildOutput.txt 10 | rad.json 11 | .output/ 12 | .dependencies/ 13 | .buildartifacts/ 14 | .alpackages/ 15 | .packages/ 16 | .alcache/ 17 | .altemplates/ 18 | .altestrunner/ 19 | .snapshots/ 20 | cache_* 21 | ~$* 22 | -------------------------------------------------------------------------------- /Templates/AppSource App/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/dynamics-smb-engineering-systems 2 | -------------------------------------------------------------------------------- /Templates/AppSource App/README.md: -------------------------------------------------------------------------------- 1 | # AL-Go AppSource App Template 2 | 3 | This template repository can be used for managing AppSource Apps for Business Central. 4 | 5 | Please go to https://aka.ms/AL-Go to learn more. 6 | 7 | ## Contributing 8 | 9 | Please read [this](https://github.com/microsoft/AL-Go/blob/main/Scenarios/Contribute.md) description on how to contribute to AL-Go for GitHub. 10 | 11 | We do not accept Pull Requests on the template repository directly. 12 | -------------------------------------------------------------------------------- /Templates/AppSource App/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This GitHub repo is auto-generated from https://github.com/microsoft/AL-Go. Issues, bug tracking and feature requests should be done there. 6 | 7 | Please follow the documentation [here](https://github.com/microsoft/AL-Go/blob/main/Scenarios/Contribute.md) if you want to contribute to AL-Go for GitHub. 8 | 9 | ## Microsoft Support Policy 10 | 11 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 12 | -------------------------------------------------------------------------------- /Templates/AppSource App/al.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".AL-Go" 5 | } 6 | ], 7 | "settings": { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.AL-Go/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "country": "us", 4 | "appFolders": [], 5 | "testFolders": [], 6 | "bcptTestFolders": [] 7 | } 8 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.github/AL-Go-Settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "type": "PTE", 4 | "templateUrl": "https://github.com/microsoft/AL-Go-PTE@main" 5 | } 6 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.github/Test Current.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "artifact": "////latest", 4 | "cacheImageName": "", 5 | "versioningStrategy": 15 6 | } 7 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.github/Test Next Major.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "artifact": "////nextmajor", 4 | "cacheImageName": "", 5 | "versioningStrategy": 15 6 | } 7 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.github/Test Next Minor.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/AL-Go-Actions/main/settings.schema.json", 3 | "artifact": "////nextminor", 4 | "cacheImageName": "", 5 | "versioningStrategy": 15 6 | } 7 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.github/workflows/Troubleshooting.yaml: -------------------------------------------------------------------------------- 1 | name: 'Troubleshooting' 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | displayNameOfSecrets: 7 | description: Display the name (not the value) of secrets available to the repository 8 | type: boolean 9 | default: false 10 | 11 | permissions: 12 | actions: read 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | shell: powershell 18 | 19 | env: 20 | ALGoOrgSettings: ${{ vars.ALGoOrgSettings }} 21 | ALGoRepoSettings: ${{ vars.ALGoRepoSettings }} 22 | 23 | jobs: 24 | Troubleshooting: 25 | runs-on: [ windows-latest ] 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | with: 30 | lfs: true 31 | 32 | - name: Troubleshooting 33 | uses: microsoft/AL-Go-Actions/Troubleshooting@main 34 | with: 35 | shell: powershell 36 | gitHubSecrets: ${{ toJson(secrets) }} 37 | displayNameOfSecrets: ${{ github.event.inputs.displayNameOfSecrets }} 38 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/.gitignore: -------------------------------------------------------------------------------- 1 | *.app 2 | *.flf 3 | *.bclicense 4 | *.g.xlf 5 | .DS_Store 6 | Thumbs.db 7 | TestResults*.xml 8 | bcptTestResults*.json 9 | BuildOutput.txt 10 | rad.json 11 | .output/ 12 | .dependencies/ 13 | .buildartifacts/ 14 | .alpackages/ 15 | .packages/ 16 | .alcache/ 17 | .altemplates/ 18 | .altestrunner/ 19 | .snapshots/ 20 | cache_* 21 | ~$* 22 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/dynamics-smb-engineering-systems 2 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/README.md: -------------------------------------------------------------------------------- 1 | # AL-Go Per Tenant Extension Template 2 | 3 | This template repository can be used for managing AppSource Apps for Business Central. 4 | 5 | Please go to https://aka.ms/AL-Go to learn more. 6 | 7 | ## Contributing 8 | 9 | Please read [this](https://github.com/microsoft/AL-Go/blob/main/Scenarios/Contribute.md) description on how to contribute to AL-Go for GitHub. 10 | 11 | We do not accept Pull Requests on the template repository directly. 12 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This GitHub repo is auto-generated from https://github.com/microsoft/AL-Go. Issues, bug tracking and feature requests should be done there. 6 | 7 | Please follow the documentation [here](https://github.com/microsoft/AL-Go/blob/main/Scenarios/Contribute.md) if you want to contribute to AL-Go for GitHub. 8 | 9 | ## Microsoft Support Policy 10 | 11 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 12 | -------------------------------------------------------------------------------- /Templates/Per Tenant Extension/al.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".AL-Go" 5 | } 6 | ], 7 | "settings": {} 8 | } 9 | -------------------------------------------------------------------------------- /Templates/README.md: -------------------------------------------------------------------------------- 1 | # AL-Go Templates 2 | 3 | ## Templates 4 | 5 | ### [Per-Tenant Extension Project](Per%20Tenant%20Extension) 6 | 7 | AL-Go template for per-tenant extensions 8 | 9 | ### [AppSource App project](AppSource%20App) 10 | 11 | AL-Go template for AppSource apps 12 | -------------------------------------------------------------------------------- /Tests/AddExistingApp.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "AddExistingApp Action Tests" { 6 | BeforeAll { 7 | $actionName = "AddExistingApp" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/CreateApp.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "CreateApp Action Tests" { 6 | BeforeAll { 7 | $actionName = "CreateApp" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/CreateDevelopmentEnvironment.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "CreateDevelopmentEnvironment Action Tests" { 6 | BeforeAll { 7 | $actionName = "CreateDevelopmentEnvironment" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/Deliver.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "Deliver Action Tests" { 6 | BeforeAll { 7 | $actionName = "Deliver" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/Deploy.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "Deploy Action Tests" { 6 | BeforeAll { 7 | $actionName = "Deploy" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | "environmentUrl" = "The URL of the deployed environment" 23 | } 24 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 25 | } 26 | 27 | # Call action 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Tests/DetermineArtifactsForRelease.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module Github-Helper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot '..\Actions\Github-Helper.psm1' -Resolve) 3 | Get-Module TestActionsHelper | Remove-Module -Force 4 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 5 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 6 | 7 | Describe 'DetermineArtifactsForRelease Tests' { 8 | BeforeAll { 9 | . (Join-Path $PSScriptRoot "..\Actions\AL-Go-Helper.ps1") 10 | 11 | $actionName = "DetermineArtifactsForRelease" 12 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 13 | $scriptName = "$actionName.ps1" 14 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 15 | $scriptPath = Join-Path $scriptRoot $scriptName 16 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 17 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 18 | } 19 | 20 | It 'Compile Action' { 21 | Invoke-Expression $actionScript 22 | } 23 | 24 | It 'Test action.yaml matches script' { 25 | $outputs = [ordered]@{ 26 | "artifacts" = "The artifacts to publish on the release" 27 | "commitish" = "The target commitish for the release" 28 | } 29 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/MarkdownLinks/AkaMSLinks.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot '../TestActionsHelper.psm1') 3 | 4 | Describe "Aka.ms links in ReleaseNotes.md should be full links" { 5 | It 'Check aka.ms links begin with https://' { 6 | $releaseNotes = Join-Path (GetRepoRoot) RELEASENOTES.md 7 | 8 | $releaseNotesContent = Get-Content -Path $releaseNotes -Encoding UTF8 -Raw 9 | $akaMSLinks = Select-String -InputObject $releaseNotesContent -Pattern 'aka.ms/' -AllMatches 10 | foreach ($match in $akaMSLinks.Matches) { 11 | # Check that aka.ms starts with https:// 12 | $releaseNotesContent.Substring($match.Index - 8, 8) | Should -Be 'https://' 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Tests/PipelineCleanup.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "PipelineCleanup Action Tests" { 6 | BeforeAll { 7 | $actionName = "PipelineCleanup" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/PullRequestStatusCheck.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "PullRequestStatusCheck Action Tests" { 6 | BeforeAll { 7 | $actionName = "PullRequestStatusCheck" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | $ENV:GITHUB_REPOSITORY = "organization/repository" 15 | $ENV:GITHUB_RUN_ID = "123456" 16 | } 17 | 18 | It 'Compile Action' { 19 | Invoke-Expression $actionScript 20 | } 21 | 22 | It 'Test action.yaml matches script' { 23 | $outputs = [ordered]@{ 24 | } 25 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 26 | } 27 | 28 | It 'should fail if there is a job that fails' { 29 | Mock -CommandName gh -MockWith {'{"total_count":3,"jobs":[{ "name": "job1", "conclusion": "success" },{ "name": "job2", "conclusion": "skipped" },{ "name": "job3", "conclusion": "failure" }]}'} 30 | { 31 | & $scriptPath 32 | } | Should -Throw -ExpectedMessage 'PR Build failed. Failing jobs: job3' 33 | } 34 | 35 | It 'should complete if there are no failing jobs' { 36 | Mock -CommandName gh -MockWith {'{"total_count":3,"jobs":[{ "name": "job1", "conclusion": "success" },{ "name": "job2", "conclusion": "skipped" },{ "name": "job3", "conclusion": "success" }]}'} 37 | Mock Write-Host {} 38 | & $scriptPath 39 | Assert-MockCalled Write-Host -Exactly 1 -Scope It -ParameterFilter { $Object -eq "PR Build succeeded" } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Tests/ReadSecrets.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "ReadSecrets Action Tests" { 6 | BeforeAll { 7 | $actionName = "ReadSecrets" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | "Secrets" = "All requested secrets in compressed JSON format" 23 | "TokenForPush" = "The token to use when workflows are pushing changes (either directly, or via pull requests)." 24 | } 25 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 26 | } 27 | 28 | # Call action 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Tests/ReadSettings.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "ReadSettings Action Tests" { 6 | BeforeAll { 7 | $actionName = "ReadSettings" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | "GitHubRunnerJson" = "GitHubRunner in compressed Json format" 23 | "GitHubRunnerShell" = "Shell for GitHubRunner jobs" 24 | } 25 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/RunPipeline.Action.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "RunPipeline Action Tests" { 6 | BeforeAll { 7 | $actionName = "RunPipeline" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/Sign.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "Sign Action Tests" { 6 | BeforeAll { 7 | $actionName = "Sign" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/Troubleshooting.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "Troubleshooting Action Tests" { 6 | BeforeAll { 7 | $actionName = "Troubleshooting" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/WorkflowPostProcess.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot 'TestActionsHelper.psm1') 3 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 4 | 5 | Describe "WorkflowPostProcess Action Tests" { 6 | BeforeAll { 7 | $actionName = "WorkflowPostProcess" 8 | $scriptRoot = Join-Path $PSScriptRoot "..\Actions\$actionName" -Resolve 9 | $scriptName = "$actionName.ps1" 10 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'scriptPath', Justification = 'False positive.')] 11 | $scriptPath = Join-Path $scriptRoot $scriptName 12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'actionScript', Justification = 'False positive.')] 13 | $actionScript = GetActionScript -scriptRoot $scriptRoot -scriptName $scriptName 14 | } 15 | 16 | It 'Compile Action' { 17 | Invoke-Expression $actionScript 18 | } 19 | 20 | It 'Test action.yaml matches script' { 21 | $outputs = [ordered]@{ 22 | } 23 | YamlTest -scriptRoot $scriptRoot -actionName $actionName -actionScript $actionScript -outputs $outputs 24 | } 25 | 26 | # Call action 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/WorkflowSanitation/WorkflowFileExtensions.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot '../TestActionsHelper.psm1') 3 | 4 | Describe "All AL-Go workflows should have the .yaml extension" { 5 | It 'All PTE workflows should have the .yaml extension' { 6 | (Join-Path $PSScriptRoot "..\..\Templates\Per Tenant Extension\.github\workflows\" -Resolve) | GetWorkflowsInPath | ForEach-Object { 7 | $_.Extension | Should -Be '.yaml' 8 | } 9 | } 10 | 11 | It 'All AppSource workflows should have the .yaml extension' { 12 | (Join-Path $PSScriptRoot "..\..\Templates\AppSource App\.github\workflows\" -Resolve) | GetWorkflowsInPath | ForEach-Object { 13 | $_.Extension | Should -Be '.yaml' 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Tests/WorkflowSanitation/WorkflowReferences.Test.ps1: -------------------------------------------------------------------------------- 1 | Get-Module TestActionsHelper | Remove-Module -Force 2 | Import-Module (Join-Path $PSScriptRoot '../TestActionsHelper.psm1') 3 | 4 | Describe "All AL-Go workflows should reference actions that come from the microsoft/AL-Go-Actions or actions/ (by GitHub)" { 5 | It 'All PTE workflows are referencing actions that come from the microsoft/AL-Go-Actions or actions/ (by GitHub)' { 6 | (Join-Path $PSScriptRoot "..\..\Templates\Per Tenant Extension\.github\workflows\" -Resolve) | GetWorkflowsInPath | ForEach-Object { 7 | TestActionsReferences -YamlPath $_.FullName 8 | } 9 | } 10 | 11 | It 'All AppSource workflows are referencing actions that come from the microsoft/AL-Go-Actions or actions/ (by GitHub)' { 12 | (Join-Path $PSScriptRoot "..\..\Templates\AppSource App\.github\workflows\" -Resolve) | GetWorkflowsInPath | ForEach-Object { 13 | TestActionsReferences -YamlPath $_.FullName 14 | } 15 | } 16 | } 17 | 18 | Describe "All AL-Go workflows should reference reusable workflows from the same repository" { 19 | It 'All PTE workflows are referencing reusable workflows from the same repository ' { 20 | (Join-Path $PSScriptRoot "..\..\Templates\Per Tenant Extension\.github\workflows\" -Resolve) | GetWorkflowsInPath | ForEach-Object { 21 | TestWorkflowReferences -YamlPath $_.FullName 22 | } 23 | } 24 | 25 | It 'All AppSource workflows are referencing reusable workflows from the same repository ' { 26 | (Join-Path $PSScriptRoot "..\..\Templates\AppSource App\.github\workflows\" -Resolve) | GetWorkflowsInPath | ForEach-Object { 27 | TestWorkflowReferences -YamlPath $_.FullName 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Tests/YamlSnippet.txt: -------------------------------------------------------------------------------- 1 | name: 'CI/CD' 2 | 3 | on: 4 | workflow_dispatch: 5 | workflow_run: 6 | workflows: ["Pull Request Handler"] 7 | types: 8 | - completed 9 | push: 10 | paths-ignore: 11 | - '**.md' 12 | - '.github/workflows/*.yaml' 13 | - '!.github/workflows/CICD.yaml' 14 | branches: [ 'main', 'release/*', 'feature/*' ] 15 | 16 | run-name: ${{ fromJson(format('["","Check pull request from {1}/{2}{0} {3}"]',':',github.event.workflow_run.head_repository.owner.login,github.event.workflow_run.head_branch,github.event.workflow_run.display_title))[github.event_name == 'workflow_run'] }} 17 | 18 | permissions: 19 | contents: read 20 | actions: read 21 | pull-requests: write 22 | checks: write 23 | 24 | defaults: 25 | run: 26 | shell: powershell 27 | 28 | env: 29 | workflowDepth: 1 30 | 31 | jobs: 32 | Initialization: 33 | if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' 34 | runs-on: [ windows-latest ] 35 | outputs: 36 | telemetryScopeJson: ${{ steps.init.outputs.telemetryScopeJson }} 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v4 40 | with: 41 | lfs: true 42 | 43 | - name: Initialize the workflow 44 | id: init 45 | uses: microsoft/AL-Go-Actions/WorkflowInitialize@main 46 | with: 47 | shell: powershell 48 | 49 | - name: Read settings 50 | id: ReadSettings 51 | uses: microsoft/AL-Go-Actions/ReadSettings@main 52 | with: 53 | shell: powershell 54 | 55 | CheckForUpdates: 56 | runs-on: [ windows-latest ] 57 | needs: [ Initialization ] 58 | if: github.event_name != 'workflow_run' 59 | steps: 60 | - name: Checkout 61 | uses: actions/checkout@v4 62 | 63 | - name: Read settings 64 | uses: microsoft/AL-Go-Actions/ReadSettings@main 65 | with: 66 | shell: powershell 67 | get: templateUrl 68 | 69 | - name: Check for updates to AL-Go system files 70 | uses: microsoft/AL-Go-Actions/CheckForUpdates@main 71 | with: 72 | shell: powershell 73 | templateUrl: ${{ env.templateUrl }} 74 | -------------------------------------------------------------------------------- /Tests/_TestData-PowerPlatform/PowerAppOnlySolution/CanvasApps/src/TestApp/DataSources/customers %28v2.0%29.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ApiId": "/providers/microsoft.powerapps/apis/shared_dynamicssmbsaas", 4 | "CdpRevision": { 5 | "BaseUrl": "/v3", 6 | "LastChangedTimeString": "2023-12-20T19:25:08.8200000Z", 7 | "RevisionNumber": 3 8 | }, 9 | "ConnectedDataSourceInfoNameMapping": { 10 | "addressLine1": "Address Line 1", 11 | "addressLine2": "Address Line 2", 12 | "balanceDue": "Balance Due", 13 | "blocked": "Blocked", 14 | "city": "City", 15 | "country": "Country/Region Code", 16 | "creditLimit": "Credit Limit", 17 | "currencyCode": "Currency Code", 18 | "currencyId": "Currency Id", 19 | "displayName": "Display Name", 20 | "email": "Email", 21 | "id": "Id", 22 | "lastModifiedDateTime": "Last Modified Date", 23 | "number": "No.", 24 | "paymentMethodId": "Payment Method Id", 25 | "paymentTermsId": "Payment Terms Id", 26 | "phoneNumber": "Phone No.", 27 | "postalCode": "ZIP Code", 28 | "salespersonCode": "Salesperson Code", 29 | "shipmentMethodId": "Shipment Method Id", 30 | "state": "State", 31 | "taxAreaDisplayName": "Tax Area Display Name", 32 | "taxAreaId": "Tax Area Id", 33 | "taxLiable": "Tax Liable", 34 | "taxRegistrationNumber": "Tax Registration No.", 35 | "type": "Type", 36 | "website": "Website" 37 | }, 38 | "DatasetName": "TestEnvironmentName,TestCompanyId", 39 | "EncodeDataset": true, 40 | "IsSampleData": false, 41 | "IsWritable": true, 42 | "Name": "customers (v2.0)", 43 | "Type": "ConnectedDataSourceInfo" 44 | } 45 | ] 46 | -------------------------------------------------------------------------------- /Tests/_TestData-PowerPlatform/PowerAppOnlySolution/CanvasApps/src/TestApp/DataSources/salesOrderLines %28v2.0%29.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ApiId": "/providers/microsoft.powerapps/apis/shared_dynamicssmbsaas", 4 | "CdpRevision": { 5 | "BaseUrl": "/v3", 6 | "LastChangedTimeString": "2023-12-20T19:25:08.8200000Z", 7 | "RevisionNumber": 3 8 | }, 9 | "ConnectedDataSourceInfoNameMapping": { 10 | "accountId": "Account Id", 11 | "amountExcludingTax": "Amount Excluding Tax", 12 | "amountIncludingTax": "Amount Including Tax", 13 | "description": "Description", 14 | "description2": "Description 2", 15 | "discountAmount": "Discount Amount", 16 | "discountAppliedBeforeTax": "Discount Applied Before Tax", 17 | "discountPercent": "Discount Percent", 18 | "documentId": "Document Id", 19 | "id": "Id", 20 | "invoiceDiscountAllocation": "Invoice Discount Allocation", 21 | "invoicedQuantity": "Invoiced Quantity", 22 | "invoiceQuantity": "Invoice Quantity", 23 | "itemId": "Item Id", 24 | "itemVariantId": "Item Variant Id", 25 | "lineObjectNumber": "Line Object No.", 26 | "lineType": "Line Type", 27 | "locationId": "Location Id", 28 | "netAmount": "Net Amount", 29 | "netAmountIncludingTax": "Net Amount Including Tax", 30 | "netTaxAmount": "Net Tax Amount", 31 | "quantity": "Quantity", 32 | "sequence": "Sequence", 33 | "shipmentDate": "Shipment Date", 34 | "shippedQuantity": "Shipped Quantity", 35 | "shipQuantity": "Ship Quantity", 36 | "taxCode": "Tax Code", 37 | "taxPercent": "Tax Percent", 38 | "totalTaxAmount": "Total Tax Amount", 39 | "unitOfMeasureCode": "Unit Of Measure Code", 40 | "unitOfMeasureId": "Unit Of Measure Id", 41 | "unitPrice": "Unit Price" 42 | }, 43 | "DatasetName": "TestEnvironmentName,TestCompanyId", 44 | "EncodeDataset": true, 45 | "IsSampleData": false, 46 | "IsWritable": true, 47 | "Name": "salesOrderLines (v2.0)", 48 | "Type": "ConnectedDataSourceInfo" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /Tests/_TestData-PowerPlatform/StandardSolution/CanvasApps/src/TestApp/DataSources/customers %28v2.0%29.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ApiId": "/providers/microsoft.powerapps/apis/shared_dynamicssmbsaas", 4 | "CdpRevision": { 5 | "BaseUrl": "/v3", 6 | "LastChangedTimeString": "2023-12-20T19:25:08.8200000Z", 7 | "RevisionNumber": 3 8 | }, 9 | "ConnectedDataSourceInfoNameMapping": { 10 | "addressLine1": "Address Line 1", 11 | "addressLine2": "Address Line 2", 12 | "balanceDue": "Balance Due", 13 | "blocked": "Blocked", 14 | "city": "City", 15 | "country": "Country/Region Code", 16 | "creditLimit": "Credit Limit", 17 | "currencyCode": "Currency Code", 18 | "currencyId": "Currency Id", 19 | "displayName": "Display Name", 20 | "email": "Email", 21 | "id": "Id", 22 | "lastModifiedDateTime": "Last Modified Date", 23 | "number": "No.", 24 | "paymentMethodId": "Payment Method Id", 25 | "paymentTermsId": "Payment Terms Id", 26 | "phoneNumber": "Phone No.", 27 | "postalCode": "ZIP Code", 28 | "salespersonCode": "Salesperson Code", 29 | "shipmentMethodId": "Shipment Method Id", 30 | "state": "State", 31 | "taxAreaDisplayName": "Tax Area Display Name", 32 | "taxAreaId": "Tax Area Id", 33 | "taxLiable": "Tax Liable", 34 | "taxRegistrationNumber": "Tax Registration No.", 35 | "type": "Type", 36 | "website": "Website" 37 | }, 38 | "DatasetName": "TestEnvironmentName,TestCompanyId", 39 | "EncodeDataset": true, 40 | "IsSampleData": false, 41 | "IsWritable": true, 42 | "Name": "customers (v2.0)", 43 | "Type": "ConnectedDataSourceInfo" 44 | } 45 | ] 46 | -------------------------------------------------------------------------------- /Tests/_TestData-PowerPlatform/StandardSolution/CanvasApps/src/TestApp/DataSources/salesOrderLines %28v2.0%29.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ApiId": "/providers/microsoft.powerapps/apis/shared_dynamicssmbsaas", 4 | "CdpRevision": { 5 | "BaseUrl": "/v3", 6 | "LastChangedTimeString": "2023-12-20T19:25:08.8200000Z", 7 | "RevisionNumber": 3 8 | }, 9 | "ConnectedDataSourceInfoNameMapping": { 10 | "accountId": "Account Id", 11 | "amountExcludingTax": "Amount Excluding Tax", 12 | "amountIncludingTax": "Amount Including Tax", 13 | "description": "Description", 14 | "description2": "Description 2", 15 | "discountAmount": "Discount Amount", 16 | "discountAppliedBeforeTax": "Discount Applied Before Tax", 17 | "discountPercent": "Discount Percent", 18 | "documentId": "Document Id", 19 | "id": "Id", 20 | "invoiceDiscountAllocation": "Invoice Discount Allocation", 21 | "invoicedQuantity": "Invoiced Quantity", 22 | "invoiceQuantity": "Invoice Quantity", 23 | "itemId": "Item Id", 24 | "itemVariantId": "Item Variant Id", 25 | "lineObjectNumber": "Line Object No.", 26 | "lineType": "Line Type", 27 | "locationId": "Location Id", 28 | "netAmount": "Net Amount", 29 | "netAmountIncludingTax": "Net Amount Including Tax", 30 | "netTaxAmount": "Net Tax Amount", 31 | "quantity": "Quantity", 32 | "sequence": "Sequence", 33 | "shipmentDate": "Shipment Date", 34 | "shippedQuantity": "Shipped Quantity", 35 | "shipQuantity": "Ship Quantity", 36 | "taxCode": "Tax Code", 37 | "taxPercent": "Tax Percent", 38 | "totalTaxAmount": "Total Tax Amount", 39 | "unitOfMeasureCode": "Unit Of Measure Code", 40 | "unitOfMeasureId": "Unit Of Measure Id", 41 | "unitPrice": "Unit Price" 42 | }, 43 | "DatasetName": "TestEnvironmentName,TestCompanyId", 44 | "EncodeDataset": true, 45 | "IsSampleData": false, 46 | "IsWritable": true, 47 | "Name": "salesOrderLines (v2.0)", 48 | "Type": "ConnectedDataSourceInfo" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /Tests/runtests.ps1: -------------------------------------------------------------------------------- 1 | # PSScriptAnalyzer 2 | # Run tests 3 | 4 | <# 5 | .SYNOPSIS 6 | Run Pester tests 7 | .PARAMETER Path 8 | The folder where the tests are located. Default is the folder where the script is located. 9 | #> 10 | param( 11 | [Parameter(Mandatory = $true)] 12 | [string] $Path 13 | ) 14 | 15 | try { 16 | $errorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 17 | 18 | Write-Host "Running tests in $Path" 19 | 20 | $result = Invoke-Pester @(Get-ChildItem -Path (Join-Path $Path "*.Test.ps1")) -passthru 21 | if ($result.FailedCount -gt 0) { 22 | Write-Host "::Error::$($result.FailedCount) tests are failing" 23 | $host.SetShouldExit(1) 24 | } 25 | } 26 | catch { 27 | Write-Host "::Error::Error when running tests. The Error was $($_.Exception.Message)" 28 | $host.SetShouldExit(1) 29 | } 30 | -------------------------------------------------------------------------------- /Workshop/Dependencies3.md: -------------------------------------------------------------------------------- 1 | # Dependencies #3 - Dependencies to third party apps 2 | 3 | Dependencies to apps from other partners... 4 | 5 | TO:DO 6 | 7 | With symbols, you can compile your app 8 | 9 | With runtime packages or the full .app file, you can also run tests 10 | 11 | ### URL to symbols of dependency1.app 12 | 13 | ### URL to runtime package of dependency1.app 14 | 15 | ### URL to full app of dependency1.app 16 | 17 | ### Add to installApps 18 | -------------------------------------------------------------------------------- /Workshop/DevelopmentEnvironments.md: -------------------------------------------------------------------------------- 1 | # FUTURE TOPIC: Development Environments 2 | 3 | This topic will be finalized later 4 | 5 | ______________________________________________________________________ 6 | 7 | [Index](Index.md)  [next](TheDevelopmentProcess.md) 8 | -------------------------------------------------------------------------------- /Workshop/KeepUpToDate.md: -------------------------------------------------------------------------------- 1 | # FUTURE TOPIC: Keeping your AL-Go repository up-to-date 2 | 3 | This topic will be finalized later 4 | 5 | ______________________________________________________________________ 6 | 7 | [Index](Index.md)  [next](Index.md) 8 | -------------------------------------------------------------------------------- /Workshop/PerformanceTesting.md: -------------------------------------------------------------------------------- 1 | # FUTURE TOPIC: Performance Testing 2 | 3 | This topic will be finalized later 4 | 5 | Testing is an important part of the app quality, but so is documentation. Let's look at generating reference documentation your app, and... - keeping it up-to-date... 6 | 7 | ______________________________________________________________________ 8 | 9 | [Index](Index.md)  [next](ReferenceDoc.md) 10 | -------------------------------------------------------------------------------- /Workshop/TheDevelopmentProcess.md: -------------------------------------------------------------------------------- 1 | # FUTURE TOPIC: The Development Process 2 | 3 | This topic will be finalized later 4 | 5 | ______________________________________________________________________ 6 | 7 | [Index](Index.md)  [next](KeepUpToDate.md) 8 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | lsi: false 2 | safe: true 3 | source: . 4 | incremental: false 5 | highlighter: rouge 6 | markdown: kramdown 7 | title: "AL-Go for GitHub" 8 | description: "The plug-and-play DevOps solution for Business Central app development on GitHub" 9 | baseurl: AL-Go/ 10 | gist: 11 | noscript: false 12 | kramdown: 13 | math_engine: mathjax 14 | syntax_highlighter: rouge 15 | remote_theme: pages-themes/architect@v0.2.0 16 | plugins: 17 | - jekyll-remote-theme 18 | - jekyll-responsive_image 19 | -------------------------------------------------------------------------------- /e2eTests/SetupRepositories.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $githubOwner, 3 | [string] $bcContainerHelperVersion = '' 4 | ) 5 | 6 | Import-Module (Join-Path $PSScriptRoot "e2eTestHelper.psm1") -DisableNameChecking 7 | 8 | $repoBaseName = [System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetTempFileName()) 9 | Write-Host $repoBaseName 10 | 11 | $actionsRepo = "$repoBaseName-Actions" 12 | $perTenantExtensionRepo = "$repoBaseName-PTE" 13 | $appSourceAppRepo = "$repoBaseName-AppSource" 14 | 15 | $config = [ordered]@{ 16 | "githubOwner" = $githubOwner 17 | "actionsRepo" = $actionsRepo 18 | "perTenantExtensionRepo" = $perTenantExtensionRepo 19 | "appSourceAppRepo" = $appSourceAppRepo 20 | "branch" = "main" 21 | "localFolder" = "" 22 | "baseFolder" = [System.IO.Path]::GetTempPath() 23 | "defaultBcContainerHelperVersion" = $bcContainerHelperVersion 24 | } 25 | 26 | . (Join-Path $PSScriptRoot "..\Internal\Deploy.ps1") -config $config -DirectCommit $true 27 | 28 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "actionsRepo=$actionsRepo" 29 | Write-Host "actionsRepo=$actionsRepo" 30 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "perTenantExtensionRepo=$perTenantExtensionRepo" 31 | Write-Host "perTenantExtensionRepo=$perTenantExtensionRepo" 32 | Add-Content -Encoding UTF8 -Path $env:GITHUB_OUTPUT -Value "appSourceAppRepo=$appSourceAppRepo" 33 | Write-Host "appSourceAppRepo=$appSourceAppRepo" 34 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunAddExistingAppOrTestApp.ps1: -------------------------------------------------------------------------------- 1 | function RunAddExistingAppOrTestApp { 2 | Param( 3 | [string] $project, 4 | [string] $url, 5 | [switch] $directCommit, 6 | [switch] $useGhTokenWorkflow, 7 | [switch] $wait, 8 | [string] $repository, 9 | [string] $branch = "main" 10 | ) 11 | 12 | $workflowName = 'Add existing app or test app' 13 | $parameters = @{ 14 | "project" = $project 15 | "url" = $url 16 | "directCommit" = @("true","false")[!$directCommit] 17 | "useGhTokenWorkflow" = @("true","false")[!$useGhTokenWorkflow] 18 | } 19 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 20 | } 21 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunCICD.ps1: -------------------------------------------------------------------------------- 1 | function RunCICD { 2 | Param( 3 | [switch] $wait, 4 | [string] $repository, 5 | [string] $branch = "main" 6 | ) 7 | 8 | $workflowName = 'CI/CD' 9 | $parameters = @{ 10 | } 11 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 12 | } 13 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunCreateApp.ps1: -------------------------------------------------------------------------------- 1 | function RunCreateApp { 2 | Param( 3 | [string] $project, 4 | [string] $name, 5 | [string] $publisher, 6 | [string] $idrange, 7 | [switch] $directCommit, 8 | [switch] $useGhTokenWorkflow, 9 | [switch] $wait, 10 | [string] $repository, 11 | [string] $branch = "main" 12 | ) 13 | 14 | $workflowName = 'Create a new app' 15 | $parameters = @{ 16 | "project" = $project 17 | "name" = $name 18 | "publisher" = $publisher 19 | "idrange" = $idrange 20 | "directCommit" = @("true","false")[!$directCommit] 21 | "useGhTokenWorkflow" = @("true","false")[!$useGhTokenWorkflow] 22 | } 23 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 24 | } 25 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunCreateOnlineDevelopmentEnvironment.ps1: -------------------------------------------------------------------------------- 1 | function RunCreateOnlineDevelopmentEnvironment { 2 | Param( 3 | [string] $environmentName, 4 | [switch] $reUseExistingEnvironment, 5 | [switch] $directCommit, 6 | [switch] $useGhTokenWorkflow, 7 | [switch] $wait, 8 | [string] $repository, 9 | [string] $branch = "main" 10 | ) 11 | 12 | $workflowName = 'Create Online Dev. Environment' 13 | $parameters = @{ 14 | "environmentName" = $environmentName 15 | "reUseExistingEnvironment" = @("true","false")[!$reUseExistingEnvironment] 16 | "directCommit" = @("true","false")[!$directCommit] 17 | "useGhTokenWorkflow" = @("true","false")[!$useGhTokenWorkflow] 18 | } 19 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 20 | } 21 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunCreateRelease.ps1: -------------------------------------------------------------------------------- 1 | function RunCreateRelease { 2 | Param( 3 | [string] $buildVersion, 4 | [string] $name, 5 | [string] $tag, 6 | [ValidateSet('Release','Draft','Prerelease')] 7 | [string] $releaseType = 'Release', 8 | [switch] $createReleaseBranch, 9 | [string] $updateVersionNumber = '', 10 | [switch] $skipUpdatingDependencies, 11 | [switch] $directCommit, 12 | [switch] $useGhTokenWorkflow, 13 | [switch] $wait, 14 | [string] $repository, 15 | [string] $branch = "main" 16 | ) 17 | 18 | $workflowName = 'Create release' 19 | $parameters = @{ 20 | "buildVersion" = $buildVersion 21 | "name" = $name 22 | "tag" = $tag 23 | "releaseType" = $releaseType 24 | "createReleaseBranch" = @("true","false")[!$createReleaseBranch] 25 | "updateVersionNumber" = $updateVersionNumber 26 | "skipUpdatingDependencies" = @("true","false")[!$skipUpdatingDependencies] 27 | "directCommit" = @("true","false")[!$directCommit] 28 | "useGhTokenWorkflow" = @("true","false")[!$useGhTokenWorkflow] 29 | } 30 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 31 | } 32 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunCreateTestApp.ps1: -------------------------------------------------------------------------------- 1 | function RunCreateTestApp { 2 | Param( 3 | [string] $project, 4 | [string] $name, 5 | [string] $publisher, 6 | [string] $idrange, 7 | [switch] $directCommit, 8 | [switch] $useGhTokenWorkflow, 9 | [switch] $wait, 10 | [string] $repository, 11 | [string] $branch = "main" 12 | ) 13 | 14 | $workflowName = 'Create a new test app' 15 | $parameters = @{ 16 | "project" = $project 17 | "name" = $name 18 | "publisher" = $publisher 19 | "idrange" = $idrange 20 | "directCommit" = @("true","false")[!$directCommit] 21 | "useGhTokenWorkflow" = @("true","false")[!$useGhTokenWorkflow] 22 | } 23 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 24 | } 25 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunDeployReferenceDocumentation.ps1: -------------------------------------------------------------------------------- 1 | function RunDeployReferenceDocumentation { 2 | Param( 3 | [switch] $wait, 4 | [string] $repository, 5 | [string] $branch = "main" 6 | ) 7 | 8 | $workflowName = 'Deploy Reference Documentation' 9 | $parameters = @{ 10 | } 11 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 12 | } 13 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunIncrementVersionNumber.ps1: -------------------------------------------------------------------------------- 1 | function RunIncrementVersionNumber { 2 | Param( 3 | [string] $projects, 4 | [string] $versionNumber, 5 | [switch] $directCommit, 6 | [switch] $useGhTokenWorkflow, 7 | [switch] $wait, 8 | [string] $repository, 9 | [string] $branch = "main" 10 | ) 11 | 12 | $workflowName = 'Increment Version Number' 13 | $parameters = @{ 14 | "projects" = $projects 15 | "versionNumber" = $versionNumber 16 | "directCommit" = @("true","false")[!$directCommit] 17 | "useGhTokenWorkflow" = @("true","false")[!$useGhTokenWorkflow] 18 | } 19 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 20 | } 21 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunPublishToEnvironment.ps1: -------------------------------------------------------------------------------- 1 | function RunPublishToEnvironment { 2 | Param( 3 | [string] $appVersion, 4 | [string] $environmentName, 5 | [switch] $wait, 6 | [string] $repository, 7 | [string] $branch = "main" 8 | ) 9 | 10 | $workflowName = 'Publish To Environment' 11 | $parameters = @{ 12 | "appVersion" = $appVersion 13 | "environmentName" = $environmentName 14 | } 15 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 16 | } 17 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunTestCurrent.ps1: -------------------------------------------------------------------------------- 1 | function RunTestCurrent { 2 | Param( 3 | [switch] $wait, 4 | [string] $repository, 5 | [string] $branch = "main" 6 | ) 7 | 8 | $workflowName = 'Test Current' 9 | $parameters = @{ 10 | } 11 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 12 | } 13 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunTestNextMajor.ps1: -------------------------------------------------------------------------------- 1 | function RunTestNextMajor { 2 | Param( 3 | [switch] $wait, 4 | [string] $repository, 5 | [string] $branch = "main" 6 | ) 7 | 8 | $workflowName = 'Test Next Major' 9 | $parameters = @{ 10 | } 11 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 12 | } 13 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunTestNextMinor.ps1: -------------------------------------------------------------------------------- 1 | function RunTestNextMinor { 2 | Param( 3 | [switch] $wait, 4 | [string] $repository, 5 | [string] $branch = "main" 6 | ) 7 | 8 | $workflowName = 'Test Next Minor' 9 | $parameters = @{ 10 | } 11 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 12 | } 13 | -------------------------------------------------------------------------------- /e2eTests/Workflows/RunUpdateAlGoSystemFiles.ps1: -------------------------------------------------------------------------------- 1 | function RunUpdateAlGoSystemFiles { 2 | Param( 3 | [string] $templateUrl, 4 | [switch] $directCommit, 5 | [switch] $wait, 6 | [string] $repository, 7 | [string] $branch = "main", 8 | [string] $ghTokenWorkflow 9 | ) 10 | 11 | if ($ghTokenWorkflow) { 12 | SetRepositorySecret -repository $repository -name 'GHTOKENWORKFLOW' -value $ghTokenWorkflow 13 | } 14 | $workflowName = 'Update AL-Go System Files' 15 | $parameters = @{ 16 | "templateUrl" = $templateUrl.Split('|')[0] 17 | "directCommit" = @("true","false")[!$directCommit] 18 | } 19 | RunWorkflow -name $workflowName -parameters $parameters -wait:$wait -branch $branch -repository $repository 20 | } 21 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App.Test/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App.Test/HelloWorld.Test.al: -------------------------------------------------------------------------------- 1 | codeunit 50000 "HelloWorld Test" 2 | { 3 | Subtype = Test; 4 | 5 | [Test] 6 | [HandlerFunctions('HelloWorldMessageHandler')] 7 | procedure TestHelloWorldMessage() 8 | var 9 | CustList: TestPage "Customer List"; 10 | begin 11 | CustList.OpenView(); 12 | CustList.Close(); 13 | if (not MessageDisplayed) then 14 | ERROR('Message was not displayed!'); 15 | end; 16 | 17 | [MessageHandler] 18 | procedure HelloWorldMessageHandler(Message: Text[1024]) 19 | begin 20 | MessageDisplayed := MessageDisplayed or (Message = 'App published: Hello world'); 21 | end; 22 | 23 | var 24 | MessageDisplayed: Boolean; 25 | } 26 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App.Test/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "d9ab0f1b-66cc-41cd-a83c-0cd78b99e876", 3 | "name": "My App.Test", 4 | "publisher": "My Publisher", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | 15 | ], 16 | "screenshots": [ 17 | 18 | ], 19 | "platform": "1.0.0.0", 20 | "application": "22.0.0.0", 21 | "idRanges": [ 22 | { 23 | "from": 50000, 24 | "to": 99999 25 | } 26 | ], 27 | "resourceExposurePolicy": { 28 | "allowDebugging": true, 29 | "allowDownloadingSource": false, 30 | "includeSourceInSymbolFile": false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // Welcome to your new AL extension. 2 | // Remember that object names and IDs should be unique across all extensions. 3 | // AL snippets start with t*, like tpageext - give them a try and happy coding! 4 | 5 | pageextension 7500000 CustomerListExt extends "Customer List" 6 | { 7 | trigger OnOpenPage(); 8 | begin 9 | Message('App published: Hello world'); 10 | end; 11 | } 12 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "b28a6f48-77c4-44ae-8fc0-6150cdee223e", 3 | "name": "My App", 4 | "publisher": "My Publisher", 5 | "version": "1.0.0.0", 6 | "brief": "Hello World for AppSource", 7 | "description": "Hello World sample app for AppSource", 8 | "privacyStatement": "https://github.com/BusinessCentralApps/helloworld.appsource", 9 | "EULA": "https://github.com/BusinessCentralApps/helloworld.appsource", 10 | "help": "https://github.com/BusinessCentralApps/helloworld.appsource", 11 | "url": "https://github.com/BusinessCentralApps/helloworld.appsource", 12 | "contextSensitiveHelpUrl": "https://github.com/BusinessCentralApps/helloworld.appsource", 13 | "logo": "helloworld256x240.png", 14 | "dependencies": [ 15 | 16 | ], 17 | "screenshots": [ 18 | 19 | ], 20 | "platform": "1.0.0.0", 21 | "application": "22.0.0.0", 22 | "idRanges": [ 23 | { 24 | "from": 7500000, 25 | "to": 7500010 26 | } 27 | ], 28 | "features": [ 29 | "TranslationFile" 30 | ], 31 | "resourceExposurePolicy": { 32 | "allowDebugging": true, 33 | "allowDownloadingSource": false, 34 | "includeSourceInSymbolFile": false 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /e2eTests/appsourceapp/My App/helloworld256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AL-Go/405966b5782867ad1d533cf2e6ba0bf5cd6b26b1/e2eTests/appsourceapp/My App/helloworld256x240.png -------------------------------------------------------------------------------- /e2eTests/orgmap.json: -------------------------------------------------------------------------------- 1 | { 2 | "microsoft": "businesscentralapps", 3 | "freddydk": "businesscentralapps", 4 | "businesscentraldemos": "businesscentralapps" 5 | } 6 | -------------------------------------------------------------------------------- /e2eTests/pte/My App.Test/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /e2eTests/pte/My App.Test/HelloWorld.Test.al: -------------------------------------------------------------------------------- 1 | codeunit 60000 "HelloWorld Test" 2 | { 3 | Subtype = Test; 4 | 5 | [Test] 6 | [HandlerFunctions('HelloWorldMessageHandler')] 7 | procedure TestHelloWorldMessage() 8 | var 9 | CustList: TestPage "Customer List"; 10 | begin 11 | CustList.OpenView(); 12 | CustList.Close(); 13 | if (not MessageDisplayed) then 14 | ERROR('Message was not displayed!'); 15 | end; 16 | 17 | [MessageHandler] 18 | procedure HelloWorldMessageHandler(Message: Text[1024]) 19 | begin 20 | MessageDisplayed := MessageDisplayed or (Message = 'App published: Hello world'); 21 | end; 22 | 23 | var 24 | MessageDisplayed: Boolean; 25 | } 26 | -------------------------------------------------------------------------------- /e2eTests/pte/My App.Test/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c93cebe0-0edc-4d84-84be-50c2f2ba6d29", 3 | "name": "My App.Test", 4 | "publisher": "My Publisher", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | 15 | ], 16 | "screenshots": [ 17 | 18 | ], 19 | "platform": "1.0.0.0", 20 | "application": "22.0.0.0", 21 | "idRanges": [ 22 | { 23 | "from": 60000, 24 | "to": 61000 25 | } 26 | ], 27 | "resourceExposurePolicy": { 28 | "allowDebugging": true, 29 | "allowDownloadingSource": false, 30 | "includeSourceInSymbolFile": false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /e2eTests/pte/My App/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /e2eTests/pte/My App/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // Welcome to your new AL extension. 2 | // Remember that object names and IDs should be unique across all extensions. 3 | // AL snippets start with t*, like tpageext - give them a try and happy coding! 4 | 5 | pageextension 50000 CustomerListExt extends "Customer List" 6 | { 7 | trigger OnOpenPage(); 8 | begin 9 | Message('App published: Hello world'); 10 | end; 11 | } 12 | -------------------------------------------------------------------------------- /e2eTests/pte/My App/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "603424b6-3769-4228-bde0-ab109409bb7f", 3 | "name": "My App", 4 | "publisher": "My Publisher", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | 15 | ], 16 | "screenshots": [ 17 | 18 | ], 19 | "platform": "1.0.0.0", 20 | "application": "22.0.0.0", 21 | "idRanges": [ 22 | { 23 | "from": 50000, 24 | "to": 51000 25 | } 26 | ], 27 | "resourceExposurePolicy": { 28 | "allowDebugging": true, 29 | "allowDownloadingSource": false, 30 | "includeSourceInSymbolFile": false 31 | } 32 | } 33 | --------------------------------------------------------------------------------