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
49 changes: 49 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Deploy

on:
push:
branches: [main]
workflow_dispatch:

env:
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/socialmedia-webapi

jobs:
build-and-push:
name: Build and Push Docker Image
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

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

- name: Log in to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Extract metadata (tags & labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-,format=short

- name: Build and push
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.prod
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
80 changes: 41 additions & 39 deletions .github/workflows/dev-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,44 @@ on:
workflow_dispatch:

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

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

- name: Build test image
uses: docker/build-push-action@v7
with:
context: .
file: Docker/Dockerfile.test
push: false
load: true
tags: socialmedia-test:${{ github.sha }}
cache-from: type=gha,scope=test-image
cache-to: type=gha,mode=max,scope=test-image
- name: Run unit tests
run: |
mkdir -p ${{ github.workspace }}/test-results/unit
docker run --rm \
-v ${{ github.workspace }}/test-results/unit:/app/test-results \
socialmedia-test:${{ github.sha }} \
--no-build \
--filter "Category=Unit" \
--logger "trx;LogFileName=unit-results.trx" \
--results-directory /app/test-results

- name: Publish unit test results
uses: dorny/test-reporter@v3
if: always()
with:
name: Unit Test Results
path: test-results/unit/*.trx
reporter: dotnet-trx
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }}
restore-keys: |
${{ runner.os }}-nuget-

- name: Restore dependencies
run: dotnet restore

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

- name: Run unit tests
run: |
dotnet test --no-build --configuration Release \
--filter "Category=Unit" \
--logger "trx;LogFileName=test-results.trx" \
--results-directory test-results/unit

- name: Publish unit test results
uses: dorny/test-reporter@v3
if: always()
with:
name: Unit Test Results
path: test-results/unit/*.trx
reporter: dotnet-trx
66 changes: 22 additions & 44 deletions .github/workflows/main-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,31 @@ jobs:
- name: Checkout
uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Build test image
uses: docker/build-push-action@v7
- name: Cache NuGet packages
uses: actions/cache@v5
with:
context: .
file: Docker/Dockerfile.test
push: false
load: true
tags: socialmedia-test:${{ github.sha }}
cache-from: type=gha,scope=test-image
cache-to: type=gha,mode=max,scope=test-image
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }}
restore-keys: |
${{ runner.os }}-nuget-

- name: Restore dependencies
run: dotnet restore

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

- name: Run unit tests
run: |
mkdir -p ${{ github.workspace }}/test-results/unit
docker run --rm \
-v ${{ github.workspace }}/test-results/unit:/app/test-results \
socialmedia-test:${{ github.sha }} \
--no-build \
dotnet test --no-build --configuration Release \
--filter "Category=Unit" \
--logger "trx;LogFileName=unit-results.trx" \
--results-directory /app/test-results
--logger "trx;LogFileName=test-results.trx" \
--results-directory test-results/unit

- name: Publish unit test results
uses: dorny/test-reporter@v3
Expand Down Expand Up @@ -72,34 +74,10 @@ jobs:
push: false
load: true
tags: socialmedia-test:${{ github.sha }}
cache-from: type=gha,scope=test-image
cache-to: type=gha,mode=max,scope=test-image

- name: Cache Testcontainers Docker images
id: cache-docker
uses: actions/cache@v5
with:
path: /tmp/docker-images
key: docker-images-${{ runner.os }}-mssql-2022-ryuk-0.14.0

- name: Load cached images
if: steps.cache-docker.outputs.cache-hit == 'true'
run: |
docker load < /tmp/docker-images/mssql.tar
docker load < /tmp/docker-images/ryuk.tar

- name: Pull and save images
if: steps.cache-docker.outputs.cache-hit != 'true'
run: |
docker pull mcr.microsoft.com/mssql/server:2022-latest
docker pull testcontainersofficial/ryuk:0.14.0
mkdir -p /tmp/docker-images
docker save mcr.microsoft.com/mssql/server:2022-latest > /tmp/docker-images/mssql.tar
docker save testcontainersofficial/ryuk:0.14.0 > /tmp/docker-images/ryuk.tar
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Run integration tests
env:
TESTCONTAINERS_RYUK_DISABLED: "false"
run: |
mkdir -p ${{ github.workspace }}/test-results/integration
docker run --rm \
Expand Down
1 change: 0 additions & 1 deletion Docker/Dockerfile.prod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ COPY . .
RUN --mount=type=cache,id=nuget-http,target=/root/.local/share/NuGet/http-cache \
--mount=type=cache,id=nuget-global,target=$NUGET_PACKAGES \
dotnet build ./SocialMedia.slnx \
--no-restore \
-c Release


Expand Down
9 changes: 4 additions & 5 deletions Docker/Dockerfile.test
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build

WORKDIR /app

ENV NUGET_PACKAGES=/root/.nuget/packages
ENV ASPNETCORE_ENVIRONMENT=Testing

COPY Directory.Packages.props .
COPY Directory.Build.props .
Expand All @@ -13,16 +15,13 @@ COPY ./tests/SocialMedia.Application.UnitTests/*.csproj ./tests/SocialMedia.Ap
COPY ./tests/SocialMedia.IntegrationTests/*.csproj ./tests/SocialMedia.IntegrationTests/
COPY ./SocialMedia.slnx .

RUN --mount=type=cache,id=nuget-http,target=/root/.local/share/NuGet/http-cache \
--mount=type=cache,id=nuget-global,target=$NUGET_PACKAGES \
RUN --mount=type=cache,target=$NUGET_PACKAGES \
dotnet restore ./SocialMedia.slnx

COPY . .

RUN --mount=type=cache,id=nuget-http,target=/root/.local/share/NuGet/http-cache \
--mount=type=cache,id=nuget-global,target=$NUGET_PACKAGES \
RUN --mount=type=cache,target=$NUGET_PACKAGES \
dotnet build ./SocialMedia.slnx \
--no-restore \
-c Debug

ENTRYPOINT ["dotnet", "test"]
Expand Down
6 changes: 4 additions & 2 deletions src/SocialMedia.WebApi/SocialMedia.WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
<Folder Include="wwwroot/uploads/users-avatars/" />
</ItemGroup>

<ItemGroup>
<None Include="Middlewares/GlobalExceptionHandler.cs" />
<ItemGroup>
<None Include="Middlewares/GlobalExceptionHandler.cs" />
</ItemGroup>



</Project>
59 changes: 59 additions & 0 deletions src/SocialMedia.WebApi/appsettings.Testing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"Serilog": {
"Using": ["Serilog.Sinks.Console", "Serilog.Sinks.Seq"],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"System": "Warning"
}
},
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "Seq",
"Args": {
"serverUrl": "http://social-seq:5341"
}
}
]
},
"ConnectionStrings": {
"sqlServerConnectionString": "Data Source=;Initial Catalog=SocialMedia;User ID=sa;Password=;Connect Timeout=30;Trust Server Certificate=True;Authentication=SqlPassword;"
},
"jwt": {
"Issuer": "SocialMedia.WebApi",
"Audience": "SocialMedia.Frontend",
"Lifetime": 60,
"RefreshTokenLifetime": 120,
"SigningKey": "your-secure-signing-key-for-jwt-tokensaklhg"
},
"email": {
"Smtp": "smtp.gmail.com",
"Port": 587,
"Username": "your-email@gmail.com",
"Password": "your-app-password",
"From": "your-email@gmail.com",
"BaseUrl": "https://localhost:5000",
"EmailVerificationPath": "/api/auth/verify-email?token={token}",
"PasswordResetPath": "/api/auth/reset-password?token={token}"
},
"supabase": {
"Url": "https://test-supabase-url.supabase.co",
"Key": "test-supabase-key"
},
"durations": {
"EmailVerificationTokenExpiryMinutes": 30,
"PasswordResetTokenExpiryMinutes": 30
},
"FileUpload": {
"Provider": "Server"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.AspNetCore.TestHost;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
Expand All @@ -29,31 +30,35 @@ public class IntegrationTestWebAppFactory : WebApplicationFactory<Program>, IAsy
.WithCleanUp(true)
.Build();
public HttpClient HttpClient { get; private set; } = null!;
private SqlConnection _dbConnection;
private SqlConnection _dbConnection = null!;
private Respawner _respawner = null!;
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);
var testConnectionString = _msSqlContainer.GetConnectionString();

builder.ConfigureTestServices(services =>
{
services.RemoveAll(typeof(DbContextOptions<AppDbContext>));
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(_msSqlContainer.GetConnectionString());
options.UseSqlServer(testConnectionString);
});

services.RemoveAll(typeof(IHostedService));

services.RemoveAll(typeof(ISqlConnectionFactory));
services.AddSingleton<ISqlConnectionFactory>(new SqlConnectionFactory(_msSqlContainer.GetConnectionString()));
services.AddSingleton<ISqlConnectionFactory>(new SqlConnectionFactory(testConnectionString));
});
}

public async ValueTask InitializeAsync()
{
await _msSqlContainer.StartAsync();
var testConnectionString = _msSqlContainer.GetConnectionString();

HttpClient = CreateClient();
_dbConnection = new SqlConnection(_msSqlContainer.GetConnectionString());
_dbConnection = new SqlConnection(testConnectionString);
await _dbConnection.OpenAsync();
_respawner = await Respawner.CreateAsync(_dbConnection, new RespawnerOptions
{
Expand Down
Loading