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
32 changes: 28 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,23 @@ jobs:

- uses: actions/setup-dotnet@v4
with:
# dotnet-version: '8.0.x'
dotnet-version: '8.0.x'

# Setup .NET SDK (installs .NET 10.0 via global.json)
- uses: actions/setup-dotnet@v4
with:
global-json-file: 'global.json'

- run: dotnet --info
- name: Display .NET info
run: dotnet --info

- name: Build PASopa.sln
run: dotnet build src/PASopa.sln

# Pack so we can validate there are no warnings/errors
# We must explicitly set the configuration parameter otherwise it defaults to Release
# Packages will include all target frameworks (net48, net8.0, net10.0 for Persistence projects)
# Note: On Windows, net48 binaries are included; on Ubuntu, net48 build is skipped but pack succeeds
- name: Pack - Formulas.Tools
run: dotnet pack --no-build -c ${{ env.Configuration }} src/PAModel/Microsoft.PowerPlatform.Formulas.Tools.csproj

Expand All @@ -49,6 +56,23 @@ jobs:
- name: Pack - Persistence.Testing
run: dotnet pack --no-build -c ${{ env.Configuration }} src/Persistence.Testing/Microsoft.PowerPlatform.PowerApps.Persistence.Testing.csproj

# Run tests
- name: Test - PASopa.sln
# Run tests for all target frameworks
# On Windows: run all projects and frameworks together
- name: Test - PASopa.sln (Windows - all frameworks)
if: runner.os == 'Windows'
run: dotnet test --no-build --solution src/PASopa.sln

# On non-Windows: run test projects individually, since they don't all support the same TFMs
# We are only testing the main test projects & frameworks on Ubuntu
- name: Test - Persistence.Tests (net10.0)
if: runner.os != 'Windows'
run: dotnet test --no-build --project src/Persistence.Tests/Persistence.Tests.csproj --framework net10.0
continue-on-error: true
- name: Test - PAModelTests (net10.0)
if: runner.os != 'Windows'
run: dotnet test --no-build --project src/PAModelTests/PAModelTests.csproj --framework net10.0
continue-on-error: true
- name: Test - YamlValidator.Tests (net8.0)
if: runner.os != 'Windows'
run: dotnet test --no-build --project src/YamlValidator.Tests/YamlValidator.Tests.csproj --framework net8.0
continue-on-error: true
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
![alt text](assets/images/yaml-redhat-settings.png)
```json
"yaml.schemas": {
"https://raw.githubusercontent.com/microsoft/PowerApps-Tooling/master/docs/pa.yaml-schema.json": "*.pa.yaml"
"https://raw.githubusercontent.com/microsoft/PowerApps-Tooling/master/docs/pa.yaml-schema.json": "*.pa.yaml"
}
```

Expand Down Expand Up @@ -52,13 +52,15 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
For a developer machine (Windows 10, WSL, Linux, macOS), install:

- [git](https://git-scm.com/downloads)
- [.NET Core SDK v6.0.x (x64)](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
- [.NET SDK 10.0.x (x64)](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) (version specified in global.json)
- [VS Code](https://code.visualstudio.com/Download)
- if on Windows: [VS2019 or VS2022 (Community edition will do)](https://visualstudio.microsoft.com/downloads/). Select at least the following workload: .NET Core cross-plat
- if on Windows: [VS2022 (Community edition will do)](https://visualstudio.microsoft.com/downloads/). Select at least the following workload: .NET desktop development (for .NET Framework 4.8 support)
- recommended VSCode extensions:
- [GitLens (eamodio.gitlens)](https://github.com/eamodio/vscode-gitlens)
- [C# (ms-vscode.csharp)](https://github.com/OmniSharp/omnisharp-vscode)

**Note:** Some projects target multiple frameworks. Building .NET Framework 4.8 targets requires Windows with the .NET Framework 4.8 Developer Pack installed.

### Building and running tests

After cloning this repo (https://github.com/microsoft/PowerApps-Language-Tooling), open a terminal/cmd/PS prompt with the dotnet executable on the path. Check with: ```dotnet --version ```
Expand Down
1 change: 1 addition & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="System.IO.Compression" Version="4.3.0" Condition="'$(TargetFramework)' == 'net48'" />
<!-- System.Text.Json is a transitive dependency of Yaml2JsonNode for netstandard2.0. Pinning to 8.0.5 for CVE-2024-43485, but can be removed on update of Yaml2JsonNode -->
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="System.Text.Encodings.Web" Version="8.0.0" />
Expand Down
10 changes: 5 additions & 5 deletions src/PAModel/Microsoft.PowerPlatform.Formulas.Tools.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<TargetFrameworks>net48;net8.0;net10.0</TargetFrameworks>
<LangVersion>12</LangVersion>

<SignAssembly>true</SignAssembly>
Expand All @@ -11,12 +11,11 @@

<PropertyGroup Label="Nuget Properties">
<Title>PowerPlatform Canvas App Tools</Title>
<Description>Preview Release: This takes a Canvas App (.msapp file) and converts to and from text files that can be checked into source control.</Description>
<Description>DEPRECATED: This takes a Canvas App (.msapp file) and converts to and from text files that can be checked into source control.</Description>
<PackageReleaseNotes>
Notice:
This package is a preview release - use at your own risk.
This package is a .NET Standard 2.0 project, intended to work with .NET Framework 4.7.2 or later, and .NET 6.0 or later
We have not stabilized on Namespace or Class names with this package as of yet and things will change as we move though the preview.
This package is DEPRECATED - use at your own risk. It is no longer receiving any updates and does not support the latest versions of
Power Apps Canvas Apps.

See https://github.com/microsoft/PowerApps-Tooling/releases for the latest release notes.
</PackageReleaseNotes>
Expand All @@ -27,6 +26,7 @@
<PackageReference Include="System.Text.Json" />
<PackageReference Include="System.Text.Encodings.Web" />
<PackageReference Include="YamlDotNet" />
<PackageReference Include="System.IO.Compression" Condition="'$(TargetFramework)' == 'net48'" />
</ItemGroup>

<ItemGroup>
Expand Down
62 changes: 43 additions & 19 deletions src/PAModel/packages.lock.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
{
"version": 2,
"dependencies": {
".NETStandard,Version=v2.0": {
"NETStandard.Library": {
"type": "Direct",
"requested": "[2.0.3, )",
"resolved": "2.0.3",
"contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
".NETFramework,Version=v4.8": {
"Newtonsoft.Json": {
"type": "Direct",
"requested": "[13.0.3, )",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"System.IO.Compression": {
"type": "Direct",
"requested": "[4.3.0, )",
"resolved": "4.3.0",
"contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg=="
},
"System.Text.Encodings.Web": {
"type": "Direct",
"requested": "[8.0.0, )",
Expand All @@ -39,7 +36,8 @@
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encodings.Web": "8.0.0",
"System.Threading.Tasks.Extensions": "4.5.4"
"System.Threading.Tasks.Extensions": "4.5.4",
"System.ValueTuple": "4.5.0"
}
},
"YamlDotNet": {
Expand All @@ -56,11 +54,6 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
Expand All @@ -72,14 +65,14 @@
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.4.0",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
"resolved": "4.5.0",
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
Expand All @@ -93,6 +86,37 @@
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
}
},
"net10.0": {
"Newtonsoft.Json": {
"type": "Direct",
"requested": "[13.0.3, )",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"System.Text.Encodings.Web": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ=="
},
"System.Text.Json": {
"type": "Direct",
"requested": "[8.0.5, )",
"resolved": "8.0.5",
"contentHash": "0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg=="
},
"YamlDotNet": {
"type": "Direct",
"requested": "[15.1.6, )",
"resolved": "15.1.6",
"contentHash": "T/cQEK/KHK96Q8kytJ4iUGDXg1/fj2Qtk6rCQeIlHYU1zTeyGVHW0QNZgREQyxZpygGMDMmrXNWt0sj5TsQnjA=="
}
},
"net8.0": {
Expand Down
9 changes: 7 additions & 2 deletions src/PAModelTests/DataSourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public void TestWhenDataSourcesIsSetToEmptyDictionary(string appName)
Assert.IsTrue(File.Exists(pathToMsApp));

var (msApp, errors) = CanvasDocument.LoadFromMsapp(pathToMsApp);
msApp._dataSourceReferences["default.cds"].dataSources = new Dictionary<string, LocalDatabaseReferenceDataSource>();
msApp._dataSourceReferences["default.cds"].dataSources = new();
errors.ThrowOnErrors();

using var sourcesTempDir = new TempDir();
Expand Down Expand Up @@ -256,7 +256,12 @@ public void TestAllUsedDataSourcesArePreserved(string appName)
errors1.ThrowOnErrors();

Assert.HasCount(msApp._dataSourceReferences["default.cds"].dataSources.Count, msApp._dataSourceReferences["default.cds"].dataSources);
foreach (var entry in msApp._dataSourceReferences["default.cds"].dataSources.Keys.OrderBy(key => key).Zip(msApp1._dataSourceReferences["default.cds"].dataSources.Keys.OrderBy(key => key)))
foreach (var entry in msApp._dataSourceReferences["default.cds"].dataSources.Keys.OrderBy(key => key)
.Zip(msApp1._dataSourceReferences["default.cds"].dataSources.Keys.OrderBy(key => key)
#if NET48 // in net48, Zip does not have an overload that has default result selector, so we need to create the tuple manually.
, resultSelector: (k1, k2) => (First: k1, Second: k2)
#endif
))
{
Assert.AreEqual(entry.First, entry.Second);
}
Expand Down
4 changes: 2 additions & 2 deletions src/PAModelTests/PAModelTests.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="MSTest.Sdk">
<!-- https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-mstest-sdk -->
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>

<TargetFrameworks>net48;net8.0;net10.0</TargetFrameworks>
<LangVersion Condition="'$(TargetFramework)' == 'net48'">10.0</LangVersion>
<SignAssembly>true</SignAssembly>
<PublicSign>true</PublicSign>
</PropertyGroup>
Expand Down
34 changes: 21 additions & 13 deletions src/PAModelTests/SmartMergeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,28 @@ public void ScreenDeletionTest()
(var msapp, var errors) = CanvasDocument.LoadFromMsapp(root);
Assert.IsFalse(errors.HasErrors);

const string screenName = "Home Screen";
MergeTester(
msapp,
(branchADoc) =>
{
// Nothing
},
(branchBDoc) =>
{
branchBDoc._screens.Remove("Home Screen", out var control);
},
(resultDoc) =>
{
Assert.IsFalse(resultDoc._screens.ContainsKey("Home Screen"));
});
msapp,
(branchADoc) =>
{
// Nothing
},
(branchBDoc) =>
{
#if NET48 // in net48, Remove does not have an overload that will return the item removed.
if (branchBDoc._screens.TryGetValue(screenName, out var control))
{
branchBDoc._screens.Remove(screenName);
}
#else
branchBDoc._screens.Remove(screenName, out var control);
#endif
},
(resultDoc) =>
{
Assert.IsFalse(resultDoc._screens.ContainsKey(screenName));
});
}

[TestMethod]
Expand Down
2 changes: 1 addition & 1 deletion src/PASopa/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Latest Yaml version is: https://github.com/microsoft/PowerApps-Language-Tooling/

You can also use this functionality stand alone, using our test console app.

Download and install the [.NET Core SDK v6.0.x (x64)](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) in order to build.
Download and install the [.NET SDK 10.0.x (x64)](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) (version specified in global.json) in order to build.
Build the test console app by running: `\build.cmd`
This will create: `\bin\Debug\PASopa\PASopa.exe`

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand Down
2 changes: 1 addition & 1 deletion src/Persistence.Tests/Persistence.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="MSTest.Sdk">
<!-- https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-mstest-sdk -->
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ namespace Microsoft.PowerPlatform.PowerApps.Persistence.Compression;

public static partial class PaArchiveExtensions
{
public static ValueTask ExtractToFileAsync(this PaArchiveEntry source, string destinationFileName, bool overwrite = false)
{
#if NET10_0_OR_GREATER
// When we support .net 10, use ExtractToFileAsync
public static async Task ExtractToFileAsync(this PaArchiveEntry source, string destinationFileName, bool overwrite = false)
{
// .net 10 supports ExtractToFileAsync
await source.ZipEntry.ExtractToFileAsync(destinationFileName, overwrite).ConfigureAwait(false);
}
#else
public static ValueTask ExtractToFileAsync(this PaArchiveEntry source, string destinationFileName, bool overwrite = false)
{
source.ZipEntry.ExtractToFile(destinationFileName, overwrite);
return ValueTask.CompletedTask;
#endif
}
#endif

/// <summary>
/// Extracts the archive to a target directory, preserving relative paths.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand Down
25 changes: 24 additions & 1 deletion src/Persistence/packages.lock.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
{
"version": 1,
"version": 2,
"dependencies": {
"net10.0": {
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Direct",
"requested": "[8.0.2, )",
"resolved": "8.0.2",
"contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg=="
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Direct",
"requested": "[8.0.3, )",
"resolved": "8.0.3",
"contentHash": "dL0QGToTxggRLMYY4ZYX5AMwBb+byQBd/5dMiZE07Nv73o6I5Are3C7eQTh7K2+A4ct0PVISSr7TZANbiNb2yQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2"
}
},
"YamlDotNet": {
"type": "Direct",
"requested": "[15.1.6, )",
"resolved": "15.1.6",
"contentHash": "T/cQEK/KHK96Q8kytJ4iUGDXg1/fj2Qtk6rCQeIlHYU1zTeyGVHW0QNZgREQyxZpygGMDMmrXNWt0sj5TsQnjA=="
}
},
"net8.0": {
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Direct",
Expand Down
Loading
Loading