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
92 changes: 92 additions & 0 deletions .github/workflows/dotnet-core.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: .NET Core CI/CD

on:
push:
branches: [ master, main, 'devin/**' ]
paths:
- '**.Core/**'
- 'SampleMvcWebApp.Core.sln'
- '.github/workflows/dotnet-core.yml'
pull_request:
branches: [ master, main ]
paths:
- '**.Core/**'
- 'SampleMvcWebApp.Core.sln'
- '.github/workflows/dotnet-core.yml'

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
dotnet-version: ['8.0.x']

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet-version }}

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

- name: Restore dependencies
run: dotnet restore SampleMvcWebApp.Core.sln

- name: Build
run: dotnet build SampleMvcWebApp.Core.sln --no-restore --configuration Release

- name: Test
run: dotnet test SampleMvcWebApp.Core.sln --no-build --configuration Release --verbosity normal --logger "trx;LogFileName=test-results.trx"

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: '**/TestResults/*.trx'

code-quality:
runs-on: ubuntu-latest
needs: build

steps:
- name: Checkout repository
uses: actions/checkout@v4

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

- name: Restore dependencies
run: dotnet restore SampleMvcWebApp.Core.sln

- name: Build with analyzers
run: dotnet build SampleMvcWebApp.Core.sln --configuration Release /p:TreatWarningsAsErrors=false

docker-build:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push'

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: false
tags: samplemvcwebapp-core:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
9 changes: 9 additions & 0 deletions DataLayer.Core/Class1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace DataLayer.Core
{
public class Class1
{

}
}
7 changes: 7 additions & 0 deletions DataLayer.Core/DataLayer.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

</Project>
55 changes: 55 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Dockerfile for SampleMvcWebApp.Core
# Multi-stage build for optimized production image

# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# Copy solution and project files first for better layer caching
COPY ["SampleMvcWebApp.Core.sln", "./"]
COPY ["SampleWebApp.Core/SampleWebApp.Core.csproj", "SampleWebApp.Core/"]
COPY ["ServiceLayer.Core/ServiceLayer.Core.csproj", "ServiceLayer.Core/"]
COPY ["DataLayer.Core/DataLayer.Core.csproj", "DataLayer.Core/"]
COPY ["Tests.Core/Tests.Core.csproj", "Tests.Core/"]

# Restore dependencies
RUN dotnet restore "SampleMvcWebApp.Core.sln"

# Copy all source code
COPY ["SampleWebApp.Core/", "SampleWebApp.Core/"]
COPY ["ServiceLayer.Core/", "ServiceLayer.Core/"]
COPY ["DataLayer.Core/", "DataLayer.Core/"]
COPY ["Tests.Core/", "Tests.Core/"]

# Build the application
WORKDIR "/src/SampleWebApp.Core"
RUN dotnet build "SampleWebApp.Core.csproj" -c Release -o /app/build

# Publish stage
FROM build AS publish
RUN dotnet publish "SampleWebApp.Core.csproj" -c Release -o /app/publish /p:UseAppHost=false

# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app

# Create non-root user for security
RUN adduser --disabled-password --gecos '' appuser && chown -R appuser /app
USER appuser

# Copy published application
COPY --from=publish /app/publish .

# Expose port 80 (standard HTTP port for containers)
EXPOSE 80

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:80/health || exit 1

# Set environment variables
ENV ASPNETCORE_URLS=http://+:80
ENV ASPNETCORE_ENVIRONMENT=Production

# Entry point
ENTRYPOINT ["dotnet", "SampleWebApp.Core.dll"]
76 changes: 76 additions & 0 deletions SampleMvcWebApp.Core.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleWebApp.Core", "SampleWebApp.Core\SampleWebApp.Core.csproj", "{B494479D-4B57-4548-86DF-53F81BA64A8C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLayer.Core", "ServiceLayer.Core\ServiceLayer.Core.csproj", "{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataLayer.Core", "DataLayer.Core\DataLayer.Core.csproj", "{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Core", "Tests.Core\Tests.Core.csproj", "{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Debug|x64.ActiveCfg = Debug|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Debug|x64.Build.0 = Debug|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Debug|x86.ActiveCfg = Debug|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Debug|x86.Build.0 = Debug|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Release|Any CPU.Build.0 = Release|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Release|x64.ActiveCfg = Release|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Release|x64.Build.0 = Release|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Release|x86.ActiveCfg = Release|Any CPU
{B494479D-4B57-4548-86DF-53F81BA64A8C}.Release|x86.Build.0 = Release|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Debug|x64.ActiveCfg = Debug|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Debug|x64.Build.0 = Debug|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Debug|x86.ActiveCfg = Debug|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Debug|x86.Build.0 = Debug|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Release|Any CPU.Build.0 = Release|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Release|x64.ActiveCfg = Release|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Release|x64.Build.0 = Release|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Release|x86.ActiveCfg = Release|Any CPU
{0FB9C08C-5C93-47A8-A4A7-F6478540EC17}.Release|x86.Build.0 = Release|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Debug|x64.ActiveCfg = Debug|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Debug|x64.Build.0 = Debug|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Debug|x86.ActiveCfg = Debug|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Debug|x86.Build.0 = Debug|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Release|Any CPU.Build.0 = Release|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Release|x64.ActiveCfg = Release|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Release|x64.Build.0 = Release|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Release|x86.ActiveCfg = Release|Any CPU
{7A8C860C-C6F6-431C-9ED2-51775A9F0B00}.Release|x86.Build.0 = Release|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Debug|x64.ActiveCfg = Debug|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Debug|x64.Build.0 = Debug|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Debug|x86.ActiveCfg = Debug|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Debug|x86.Build.0 = Debug|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Release|Any CPU.Build.0 = Release|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Release|x64.ActiveCfg = Release|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Release|x64.Build.0 = Release|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Release|x86.ActiveCfg = Release|Any CPU
{815C19E1-E09B-4BC1-9AF9-DDB8ABD5F9F3}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
44 changes: 44 additions & 0 deletions SampleWebApp.Core/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
25 changes: 25 additions & 0 deletions SampleWebApp.Core/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
19 changes: 19 additions & 0 deletions SampleWebApp.Core/SampleWebApp.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.17" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ServiceLayer.Core\ServiceLayer.Core.csproj" />
<ProjectReference Include="..\DataLayer.Core\DataLayer.Core.csproj" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions SampleWebApp.Core/SampleWebApp.Core.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@SampleWebApp.Core_HostAddress = http://localhost:5174

GET {{SampleWebApp.Core_HostAddress}}/weatherforecast/
Accept: application/json

###
8 changes: 8 additions & 0 deletions SampleWebApp.Core/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
12 changes: 12 additions & 0 deletions SampleWebApp.Core/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"ConnectionStrings": {
"SampleWebAppDb": "Data Source=(localdb)\\mssqllocaldb;Initial Catalog=SampleWebAppDb;MultipleActiveResultSets=True;Integrated Security=SSPI;Trusted_Connection=True"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
9 changes: 9 additions & 0 deletions ServiceLayer.Core/Class1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace ServiceLayer.Core
{
public class Class1
{

}
}
11 changes: 11 additions & 0 deletions ServiceLayer.Core/ServiceLayer.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\DataLayer.Core\DataLayer.Core.csproj" />
</ItemGroup>

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

</Project>
Loading