Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ TestResults.xml
**/.pbi/localSettings.json
**/.pbi/cache.abf

# App Views in GDL development
src/Views/**

# Exceptions
!src/System Application/Test/Extension Management/testArtifacts/*.app
!src/Apps/IN/INTaxBase/app/Translations/India Tax Base.en-US.xlf
Expand Down
89 changes: 85 additions & 4 deletions LOCAL_DEV_ENV.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ In order to create it, simply run `.\build\scripts\DevEnv\NewDevEnv.ps1` with th

Running the above will
* Create a new container (if one doesn't already exist)
* Set up launch.jsons and settings.jsons in your VSCode
* Set up launch.jsons and settings.jsons in your VSCode


### Example - Set up a container, VSCode and publish a new system app
Expand All @@ -29,7 +29,7 @@ Running the above will
```
Running the above will
* Create a new container (if one doesn't already exist)
* Set up launch.jsons and settings.jsons in your VSCode
* Set up launch.jsons and settings.jsons in your VSCode
* Compile and publish a new system app using your local codebase

### Example - Set up a container, VSCode and publish a new system app and tests
Expand All @@ -38,5 +38,86 @@ Running the above will
```
Running the above will
* Create a new container (if one doesn't already exist)
* Set up launch.jsons and settings.jsons in your VSCode
* Compile and publish all AL apps that match `.\src\System Application\`
* Set up launch.jsons and settings.jsons in your VSCode
* Compile and publish all AL apps that match `.\src\System Application\`

## GDL development (layers and views)

Anything that ships in multiple localizations (the **Base Application** and the application layers) lives under `src/Layers`, organized by country/region. Each country's app is composed by overlapping multiple **layers** in order: a `W1` ("worldwide") base, optional regional layers, and the country layer. For example, the `US` app is composed of `W1` + `NA` + `US`, where each layer either introduces new objects or replaces objects from a base layer.

Because the source is split across layers, you don't edit the layer folders directly. Instead, you compose the layers into a single, unified **view** that can be opened in VSCode as a regular AL project. A view is materialized under `src/Views/<CountryCode>` (this folder is git-ignored). The view uses symbolic links/junctions back into `src/Layers`, so the file you see in the view is the same file as in the layer it originates from.

> **Prerequisite:** Creating a view requires permission to create symbolic links on Windows. Either enable [Developer Mode](https://learn.microsoft.com/windows/apps/get-started/enable-your-device-for-development) or run your shell as Administrator.

All commands are provided by the `GDLDevelopment` PowerShell module. Import it once per session:

```powershell
Import-Module .\build\scripts\GDLDevelopment\GDLDevelopment.psm1
```

### Create a view

```powershell
New-GDLView -CountryCode US -skipSetupDevelopmentSettings
```

This composes the layers for the given country/region into `src/Views/US`. Open the resulting `src/Views/US` folder in VSCode and develop as you would in any AL project.

> **Note:** Automatic configuration of the VSCode `launch.json`/`settings.json` (i.e. running `New-GDLView` without `-skipSetupDevelopmentSettings`) is currently broken and will be fixed later. For now, pass `-skipSetupDevelopmentSettings` and configure the projects manually if needed.

### Synchronize your changes back to the layers

Files you edit in the view update the underlying layer file directly (they are linked). New files you add in the view are real files that must be copied into the correct layer. Run:

```powershell
Sync-GDLView -CountryCode US
```

This copies any new files from the view into the layer, recreates the view (creating the appropriate links), and leaves the view in a clean, synchronized state. To also propagate files you **moved or deleted** in the view back to the layers, use:

```powershell
Sync-GDLView -CountryCode US -SyncMovesAndDeletes
```

When a moved/deleted file exists in more than one layer, you'll be prompted to choose how the change should be applied.

### Remove a view

When you're done, remove the view to clean up the links:

```powershell
Remove-GDLView -CountryCode US
```

`Remove-GDLView` first verifies the view has no unsynchronized changes. To discard any unsynchronized files and remove the view anyway, add `-Force`. To remove every view at once, use `Remove-AllGDLViews` (optionally with `-Force`).

## Miapp (propagating changes across layers)

When you change a file in the `W1` (worldwide) base layer, the same change often needs to be applied to the country-specific layers that build on top of it. **Miapp** (Micro Application Integration) is a PowerShell tool that automates this propagation: it finds the files you changed in `W1` and merges them into each dependent country layer (`AT`, `AU`, `BE`, `DE`, `US`, ...), resolving conflicts automatically or with a merge tool.

Import the module and run `Invoke-Miapp` from the repository root:

```powershell
Import-Module .\build\scripts\Miapp\MicroApp.psm1
Invoke-Miapp
```

`Invoke-Miapp` validates the repository state, discovers the files that need integrating, merges them into every dependent layer, and stages the result. Commonly used options:

```powershell
# Only propagate to a single country layer
Invoke-Miapp -Country DE

# Only propagate files matching a regex
Invoke-Miapp -FileNameFilter '\.al$'

# Resolve conflicts automatically, preferring the W1 (source) version
Invoke-Miapp -AutoResolve theirs

# Prompt before propagating each file
Invoke-Miapp -Interactive
```

> **Tip:** Run Miapp after committing your `W1` changes — it compares against the base branch (`origin/HEAD`, typically `main`) to determine what to propagate.

For the full list of parameters, the integration workflow, configuration, and troubleshooting, see the [Miapp README](build/scripts/Miapp/README.md).
17 changes: 9 additions & 8 deletions build/scripts/Miapp/MicroAppGitHelper.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -414,14 +414,15 @@ function Get-GitCurrentRemoteBranch {
[OutputType([string])]
param()

try {
(git rev-parse --symbolic-full-name '@{u}' 2>&1).ToString()
} catch {
$allowedErrors = @('fatal: no upstream configured for branch *')
$ex = $_.Exception
if(-not ($allowedErrors | ? { $ex.Message -ilike $_})) {
Throw $_
}
[string] $output = (git rev-parse --symbolic-full-name '@{u}' 2>&1)

if ($LASTEXITCODE -eq 0) {
return $output
}

$allowedErrors = @('fatal: no upstream configured for branch *')
if(-not ($allowedErrors | ? { $output -ilike $_})) {
Throw $output
}
}

Expand Down
Loading