Skip to content
Open
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
55 changes: 55 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI - Build, Test, SonarCloud

on:
push:
branches: [ feature/sonarcloud-integration, master ]
pull_request:
branches: [ feature/sonarcloud-integration, master ]

jobs:
build-and-analyze:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: "8.0.x"

- name: Restore dependencies
run: dotnet restore

- name: Install SonarScanner
run: |
dotnet tool install --global dotnet-sonarscanner --version 5.14.0 || true
echo "$HOME/.dotnet/tools" >> $GITHUB_PATH

- name: SonarCloud - Begin Analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
dotnet sonarscanner begin \
/k:"ubaidali247_bp" \
/o:"ubaidali247" \
/d:sonar.login="${SONAR_TOKEN}" \
/d:sonar.host.url="https://sonarcloud.io" \
/d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml"

- name: Clean
run: dotnet clean

- name: Build
run: dotnet build --configuration Release --no-restore

- name: Test and Generate Coverage
run: dotnet test tests/BPCalculator.Tests/BPCalculator.Tests.csproj --verbosity normal /p:CollectCoverage=true /p:CoverletOutput=coverage.opencover.xml /p:CoverletOutputFormat=opencover

- name: SonarCloud - End Analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: dotnet sonarscanner end /d:sonar.login="${SONAR_TOKEN}"
55 changes: 55 additions & 0 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI - Build, Test, SonarCloud

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
build-and-analyze:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: "8.0.x"

- name: Restore dependencies
run: dotnet restore

- name: Install SonarScanner
run: |
dotnet tool install --global dotnet-sonarscanner --version 5.14.0 || true
echo "$HOME/.dotnet/tools" >> $GITHUB_PATH

- name: SonarCloud - Begin Analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
dotnet sonarscanner begin \
/k:"ubaidali247_bp" \
/o:"ubaidali247" \
/d:sonar.login="${SONAR_TOKEN}" \
/d:sonar.host.url="https://sonarcloud.io" \
/d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml"

- name: Clean
run: dotnet clean

- name: Build
run: dotnet build --configuration Release --no-restore

- name: Test and Generate Coverage
run: dotnet test tests/BPCalculator.Tests/BPCalculator.Tests.csproj --verbosity normal /p:CollectCoverage=true /p:CoverletOutput=coverage.opencover.xml /p:CoverletOutputFormat=opencover

- name: SonarCloud - End Analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: dotnet sonarscanner end /d:sonar.login="${SONAR_TOKEN}"
50 changes: 50 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
# Build outputs
bin/
obj/

# User-specific files
.vs/
.vscode/
.idea/
*.user
*.swp
*.swo

# OS files
.DS_Store
Thumbs.db

# NuGet
*.nupkg
*.snupkg
**/packages/**
*.nuget.props
*.nuget.targets

# Logs
*.log
logs/

# Tooling caches
.dotnet/
.templateengine/

# Test results & coverage
TestResults/
coverage/

# Generated files
*.generated.cs
*.g.cs
*.g.i.cs

# Publish output
wwwroot/lib/

# Rider / JetBrains
.fleet/
.idea/
.ionide/

# Azure functions local settings
local.settings.json
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

Expand Down
6 changes: 6 additions & 0 deletions BPCalculator.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30002.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BPCalculator", "BPCalculator\BPCalculator.csproj", "{5966DA6C-819D-4303-ADC7-425B8541EC84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BPCalculator.Tests", "tests\BPCalculator.Tests\BPCalculator.Tests.csproj", "{A74C6C1D-7E2B-4A9A-B2F6-022F8D4AB9AF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -15,6 +17,10 @@ Global
{5966DA6C-819D-4303-ADC7-425B8541EC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5966DA6C-819D-4303-ADC7-425B8541EC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5966DA6C-819D-4303-ADC7-425B8541EC84}.Release|Any CPU.Build.0 = Release|Any CPU
{A74C6C1D-7E2B-4A9A-B2F6-022F8D4AB9AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A74C6C1D-7E2B-4A9A-B2F6-022F8D4AB9AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A74C6C1D-7E2B-4A9A-B2F6-022F8D4AB9AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A74C6C1D-7E2B-4A9A-B2F6-022F8D4AB9AF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 1 addition & 1 deletion BPCalculator/BPCalculator.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
19 changes: 16 additions & 3 deletions BPCalculator/BloodPressure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,22 @@ public BPCategory Category
{
get
{
// implement as part of project
//throw new NotImplementedException("not implemented yet");
return new BPCategory(); // replace this
if (Systolic >= 140 || Diastolic >= 90)
{
return BPCategory.High;
}

if (Systolic >= 120 || Diastolic >= 80)
{
return BPCategory.PreHigh;
}

if (Systolic >= 90 && Diastolic >= 60)
{
return BPCategory.Ideal;
}

return BPCategory.Low;
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions BPCalculator/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using BPCalculator.Services;

// page model

namespace BPCalculator.Pages
{
public class BloodPressureModel : PageModel
{
private readonly ITelemetryService _telemetry;

public BloodPressureModel(ITelemetryService telemetry)
{
_telemetry = telemetry;
}

[BindProperty] // bound on POST
public BloodPressure BP { get; set; }

Expand All @@ -24,6 +32,11 @@ public IActionResult OnPost()
{
ModelState.AddModelError("", "Systolic must be greater than Diastolic");
}

if (ModelState.IsValid)
{
_telemetry.TrackCalculation(BP);
}
return Page();
}
}
Expand Down
39 changes: 39 additions & 0 deletions BPCalculator/Services/TelemetryService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Diagnostics;
using Microsoft.Extensions.Logging;

namespace BPCalculator.Services
{
public interface ITelemetryService
{
void TrackCalculation(BloodPressure reading);
}

public sealed class TelemetryService : ITelemetryService
{
private static readonly ActivitySource ActivitySource = new("BPCalculator.Telemetry");
private readonly ILogger<TelemetryService> _logger;

public TelemetryService(ILogger<TelemetryService> logger)
{
_logger = logger;
}

public void TrackCalculation(BloodPressure reading)
{
if (reading == null)
{
return;
}

var category = reading.Category;

using var activity = ActivitySource.StartActivity("BloodPressureCalculation");
activity?.SetTag("bp.systolic", reading.Systolic);
activity?.SetTag("bp.diastolic", reading.Diastolic);
activity?.SetTag("bp.category", category.ToString());

_logger.LogInformation("Telemetry: {Systolic}/{Diastolic} => {Category}", reading.Systolic, reading.Diastolic, category);
}
}
}

2 changes: 2 additions & 0 deletions BPCalculator/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using BPCalculator.Services;

namespace BPCalculator
{
Expand All @@ -22,6 +23,7 @@ public Startup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITelemetryService, TelemetryService>();
services.AddRazorPages();
}

Expand Down
28 changes: 28 additions & 0 deletions tests/BPCalculator.Tests/BPCalculator.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="coverlet.msbuild" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\\..\\BPCalculator\\BPCalculator.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>

21 changes: 21 additions & 0 deletions tests/BPCalculator.Tests/BloodPressureCategoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using BPCalculator;

namespace BPCalculator.Tests;

public class BloodPressureCategoryTests
{
[Theory]
[InlineData(140, 60, BPCategory.High)]
[InlineData(120, 90, BPCategory.High)]
[InlineData(139, 89, BPCategory.PreHigh)]
[InlineData(120, 79, BPCategory.PreHigh)]
[InlineData(119, 79, BPCategory.Ideal)]
[InlineData(90, 60, BPCategory.Ideal)]
[InlineData(89, 59, BPCategory.Low)]
public void Category_Computes_As_Expected(int sys, int dia, BPCategory expected)
{
var bp = new BloodPressure { Systolic = sys, Diastolic = dia };
Assert.Equal(expected, bp.Category);
}
}

30 changes: 30 additions & 0 deletions tests/BPCalculator.Tests/TelemetryServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using BPCalculator;
using BPCalculator.Services;
using Microsoft.Extensions.Logging;

namespace BPCalculator.Tests;

public class TelemetryServiceTests
{
private static ILogger<TelemetryService> CreateLogger() =>
LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Information))
.CreateLogger<TelemetryService>();

[Fact]
public void TrackCalculation_Ignores_Null()
{
var telemetry = new TelemetryService(CreateLogger());

telemetry.TrackCalculation(null);
}

[Fact]
public void TrackCalculation_Works_For_Valid_Reading()
{
var telemetry = new TelemetryService(CreateLogger());
var reading = new BloodPressure { Systolic = 120, Diastolic = 80 };

telemetry.TrackCalculation(reading);
}
}

Loading