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
12 changes: 6 additions & 6 deletions .github/workflows/account-management.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install Node Modules
working-directory: application
Expand Down Expand Up @@ -106,15 +106,15 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
if [[ "${{ vars.SONAR_PROJECT_KEY }}" == "" ]]; then
if [[ "${{ vars.SONAR_PROJECT_KEY }}" == "" ]] || [[ "${{ vars.SONAR_ORGANIZATION }}" == "" ]] || [[ "${{ secrets.SONAR_TOKEN }}" == "" ]]; then
echo "SonarCloud is not enabled. Skipping SonarCloud analysis."
dotnet build account-management/AccountManagement.slnf --no-restore /p:Version=${{ steps.generate_version.outputs.version }} &&
dotnet dotcover test account-management/AccountManagement.slnf --no-build --dcOutput=coverage/dotCover.html --dcReportType=HTML --dcFilters="+:PlatformPlatform.*;-:*.Tests;-:type=*.AppHost.*"
dotnet test account-management/AccountManagement.slnf --no-build
else
dotnet sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.dotcover.reportsPaths="coverage/dotCover.html" &&
dotnet sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.dotcover.reportsPaths="coverage/dotCover.html" &&
dotnet build account-management/AccountManagement.slnf --no-restore /p:Version=${{ steps.generate_version.outputs.version }} &&
dotnet dotcover test account-management/AccountManagement.slnf --no-build --dcOutput=coverage/dotCover.html --dcReportType=HTML --dcFilters="+:PlatformPlatform.*;-:*.Tests;-:type=*.AppHost.*" &&
dotnet sonarscanner end /d:sonar.login="${SONAR_TOKEN}"
dotnet sonarscanner end
fi

- name: Build Frontend Artifacts
Expand Down Expand Up @@ -165,7 +165,7 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install Node Modules
working-directory: application
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/app-gateway.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install Node Modules
working-directory: application
Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install Node Modules
working-directory: application
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/back-office.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install Node Modules
working-directory: application
Expand Down Expand Up @@ -106,15 +106,15 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
if [[ "${{ vars.SONAR_PROJECT_KEY }}" == "" ]]; then
if [[ "${{ vars.SONAR_PROJECT_KEY }}" == "" ]] || [[ "${{ vars.SONAR_ORGANIZATION }}" == "" ]] || [[ "${{ secrets.SONAR_TOKEN }}" == "" ]]; then
echo "SonarCloud is not enabled. Skipping SonarCloud analysis."
dotnet build back-office/BackOffice.slnf --no-restore /p:Version=${{ steps.generate_version.outputs.version }} &&
dotnet dotcover test back-office/BackOffice.slnf --no-build --dcOutput=coverage/dotCover.html --dcReportType=HTML --dcFilters="+:PlatformPlatform.*;-:*.Tests;-:type=*.AppHost.*"
dotnet test back-office/BackOffice.slnf --no-build
else
dotnet sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.dotcover.reportsPaths="coverage/dotCover.html" &&
dotnet sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.dotcover.reportsPaths="coverage/dotCover.html" &&
dotnet build back-office/BackOffice.slnf --no-restore /p:Version=${{ steps.generate_version.outputs.version }} &&
dotnet dotcover test back-office/BackOffice.slnf --no-build --dcOutput=coverage/dotCover.html --dcReportType=HTML --dcFilters="+:PlatformPlatform.*;-:*.Tests;-:type=*.AppHost.*" &&
dotnet sonarscanner end /d:sonar.login="${SONAR_TOKEN}"
dotnet sonarscanner end
fi

- name: Build Frontend Artifacts
Expand Down Expand Up @@ -165,7 +165,7 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install Node Modules
working-directory: application
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,8 @@ playwright-report/
**/playwright/.cache/
**/.auth/

# .NET Aspire
**/.aspire/settings.json

# PlatformPlatform agent workspace
.workspace
18 changes: 7 additions & 11 deletions application/AppGateway/ApiAggregation/ApiAggregationService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
using Microsoft.OpenApi.Writers;
using Microsoft.OpenApi;
using Yarp.ReverseProxy.Configuration;

namespace PlatformPlatform.AppGateway.ApiAggregation;
Expand Down Expand Up @@ -28,7 +26,7 @@
Paths = new OpenApiPaths(),
Components = new OpenApiComponents
{
Schemas = new Dictionary<string, OpenApiSchema>()
Schemas = new Dictionary<string, IOpenApiSchema>()
}
};

Expand Down Expand Up @@ -72,17 +70,14 @@
response.EnsureSuccessStatusCode();

await using var stream = await response.Content.ReadAsStreamAsync();
var reader = new OpenApiStreamReader();
var openApiDocument = reader.Read(stream, out _);
return openApiDocument;
var (openApiDocument, _) = await OpenApiDocument.LoadAsync(stream);
return openApiDocument ?? throw new InvalidOperationException($"Failed to load OpenAPI document from {clusterOpenApiUrl}");
}

private void CombineOpenApiDocuments(OpenApiDocument aggregatedOpenApiDocument, OpenApiDocument openApiDocument)
{
if (openApiDocument.Paths is null) return;

// Merge paths
foreach (var path in openApiDocument.Paths)

Check warning on line 80 in application/AppGateway/ApiAggregation/ApiAggregationService.cs

View workflow job for this annotation

GitHub Actions / Build and Test

Loops should be simplified using the "Where" LINQ method (https://rules.sonarsource.com/csharp/RSPEC-3267)

Check warning on line 80 in application/AppGateway/ApiAggregation/ApiAggregationService.cs

View workflow job for this annotation

GitHub Actions / Build and Test

Loops should be simplified using the "Where" LINQ method (https://rules.sonarsource.com/csharp/RSPEC-3267)
{
if (!aggregatedOpenApiDocument.Paths.ContainsKey(path.Key))
{
Expand All @@ -91,7 +86,7 @@
}

// Merge schemas
if (openApiDocument.Components?.Schemas is not null)
if (openApiDocument.Components?.Schemas is not null && aggregatedOpenApiDocument.Components?.Schemas is not null)
{
foreach (var schema in openApiDocument.Components.Schemas)
{
Expand All @@ -106,9 +101,10 @@
}
}

var serverUrl = openApiDocument.Servers?.FirstOrDefault()?.Url ?? "unknown";
logger.LogInformation(
"Successfully fetched and merged OpenAPI document for {ServerUrl}",
openApiDocument.Servers.Single().Url
serverUrl
);
}

Expand Down
9 changes: 4 additions & 5 deletions application/AppGateway/AppGateway.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.OpenApi" />
<PackageReference Include="Microsoft.OpenApi.Readers" />
<PackageReference Include="Scalar.AspNetCore" />
<PackageReference Include="Yarp.ReverseProxy" />
<PackageReference Include="Microsoft.OpenApi"/>
<PackageReference Include="Scalar.AspNetCore"/>
<PackageReference Include="Yarp.ReverseProxy"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\shared-kernel\SharedKernel\SharedKernel.csproj" />
<ProjectReference Include="..\shared-kernel\SharedKernel\SharedKernel.csproj"/>
</ItemGroup>

</Project>
9 changes: 3 additions & 6 deletions application/AppGateway/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
.AddConfigFilter<ClusterDestinationConfigFilter>()
.AddConfigFilter<ApiExplorerRouteFilter>().AddTransforms(
context => context.RequestTransforms.Add(context.Services.GetRequiredService<BlockInternalApiTransform>())
.AddConfigFilter<ApiExplorerRouteFilter>().AddTransforms(context => context.RequestTransforms.Add(context.Services.GetRequiredService<BlockInternalApiTransform>())
);

if (SharedInfrastructureConfiguration.IsRunningInAzure)
Expand All @@ -33,8 +32,7 @@
else
{
builder.Services.AddSingleton<SharedAccessSignatureRequestTransform>();
reverseProxyBuilder.AddTransforms(
context => context.RequestTransforms.Add(context.Services.GetRequiredService<SharedAccessSignatureRequestTransform>())
reverseProxyBuilder.AddTransforms(context => context.RequestTransforms.Add(context.Services.GetRequiredService<SharedAccessSignatureRequestTransform>())
);
}

Expand All @@ -44,7 +42,7 @@

builder.Services.AddHttpClient(
"AccountManagement",
client => { client.BaseAddress = new Uri(Environment.GetEnvironmentVariable("ACCOUNT_MANAGEMENT_API_URL") ?? "https://localhost:9100"); }

Check warning on line 45 in application/AppGateway/Program.cs

View workflow job for this annotation

GitHub Actions / Build and Test

Refactor your code not to use hardcoded absolute paths or URIs. (https://rules.sonarsource.com/csharp/RSPEC-1075)

Check warning on line 45 in application/AppGateway/Program.cs

View workflow job for this annotation

GitHub Actions / Build and Test

Refactor your code not to use hardcoded absolute paths or URIs. (https://rules.sonarsource.com/csharp/RSPEC-1075)
);

builder.Services
Expand All @@ -71,8 +69,7 @@
options
.WithOpenApiRoutePattern("/openapi/v1.json")
.WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient)
.WithTitle("PlatformPlatform API")
.WithSidebar(true);
.WithTitle("PlatformPlatform API");
}
);

Expand Down
30 changes: 15 additions & 15 deletions application/AppHost/AppHost.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">

<Sdk Name="Aspire.AppHost.Sdk" Version="9.2.0" />
<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.2"/>

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -11,23 +11,23 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\account-management\Api\AccountManagement.Api.csproj" />
<ProjectReference Include="..\account-management\WebApp\AccountManagement.WebApp.esproj" />
<ProjectReference Include="..\account-management\Workers\AccountManagement.Workers.csproj" />
<ProjectReference Include="..\AppGateway\AppGateway.csproj" />
<ProjectReference Include="..\back-office\Api\BackOffice.Api.csproj" />
<ProjectReference Include="..\back-office\WebApp\BackOffice.WebApp.esproj" />
<ProjectReference Include="..\back-office\Workers\BackOffice.Workers.csproj" />
<ProjectReference Include="..\account-management\Api\AccountManagement.Api.csproj"/>
<ProjectReference Include="..\account-management\WebApp\AccountManagement.WebApp.esproj"/>
<ProjectReference Include="..\account-management\Workers\AccountManagement.Workers.csproj"/>
<ProjectReference Include="..\AppGateway\AppGateway.csproj"/>
<ProjectReference Include="..\back-office\Api\BackOffice.Api.csproj"/>
<ProjectReference Include="..\back-office\WebApp\BackOffice.WebApp.esproj"/>
<ProjectReference Include="..\back-office\Workers\BackOffice.Workers.csproj"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aspire.Azure.Storage.Blobs" />
<PackageReference Include="Aspire.Hosting.AppHost" />
<PackageReference Include="Aspire.Hosting.Azure.Storage" />
<PackageReference Include="Aspire.Hosting.NodeJs" />
<PackageReference Include="Aspire.Hosting.SqlServer" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" />
<PackageReference Include="Aspire.Azure.Storage.Blobs"/>
<PackageReference Include="Aspire.Hosting.AppHost"/>
<PackageReference Include="Aspire.Hosting.Azure.Storage"/>
<PackageReference Include="Aspire.Hosting.NodeJs"/>
<PackageReference Include="Aspire.Hosting.SqlServer"/>
<PackageReference Include="Microsoft.Extensions.Configuration"/>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets"/>
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions application/AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

var builder = DistributedApplication.CreateBuilder(args);

var certificatePassword = builder.CreateSslCertificateIfNotExists();
var certificatePassword = await builder.CreateSslCertificateIfNotExists();

SecretManagerHelper.GenerateAuthenticationTokenSigningKey("authentication-token-signing-key");

Expand Down Expand Up @@ -122,7 +122,7 @@ void CheckPortAvailability()
if (blocked.Any())
{
Console.WriteLine($"⚠️ Port conflicts: {string.Join(", ", blocked.Select(b => $"{b.Item1} ({b.Item2})"))}");
Console.WriteLine(" Services already running. Please run 'pp watch --stop' first.");
Console.WriteLine(" Services already running. Stop them first using 'watch --stop' command or the watch MCP tool with stop flag.");
Environment.Exit(1);
}

Expand Down
5 changes: 3 additions & 2 deletions application/AppHost/SslCertificateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ public static class SslCertificateManager
{
private static string UserSecretsId => Assembly.GetEntryAssembly()!.GetCustomAttribute<UserSecretsIdAttribute>()!.UserSecretsId;

public static string CreateSslCertificateIfNotExists(this IDistributedApplicationBuilder builder)
public static async Task<string> CreateSslCertificateIfNotExists(this IDistributedApplicationBuilder builder, CancellationToken cancellationToken = default)
{
var config = new ConfigurationBuilder().AddUserSecrets(UserSecretsId).Build();

const string certificatePasswordKey = "certificate-password";
var certificatePassword = config[certificatePasswordKey]
?? builder.CreateStablePassword(certificatePasswordKey).Resource.Value;
?? await builder.CreateStablePassword(certificatePasswordKey).Resource.GetValueAsync(cancellationToken)
?? throw new InvalidOperationException("Failed to retrieve or create certificate password.");

var certificateLocation = GetCertificateLocation("localhost");
try
Expand Down
Loading
Loading