Skip to content

Commit 65e9d8a

Browse files
authored
Merge pull request #28 from sentemon/basic-setup-for-file-storage-service
Basic Setup for File Service and Some Refactoring
2 parents 6caf14e + 803755e commit 65e9d8a

25 files changed

+658
-1
lines changed

.github/workflows/auth.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
IMAGE_VERSION=${GITHUB_REF#refs/tags/}
4848
fi
4949
docker buildx build \
50-
-t ${{ secrets.DOCKER_HUB_USERNAME }}/post-service:${IMAGE_VERSION} \
50+
-t ${{ secrets.DOCKER_HUB_USERNAME }}/auth-service:${IMAGE_VERSION} \
5151
-f ./backend/src/AuthService/Dockerfile \
5252
./backend/src
5353

.github/workflows/compose-build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ jobs:
2929
curl --fail http://0.0.0.0:8000/auth/health && break || sleep 5
3030
done
3131
curl --fail http://0.0.0.0:8000/auth/health || exit 1
32+
33+
- name: Health Check FileService
34+
run: |
35+
echo "Checking health..."
36+
for i in {1..10}; do
37+
curl --fail http://0.0.0.0:8000/file/health && break || sleep 5
38+
done
39+
curl --fail http://0.0.0.0:8000/file/health || exit 1
3240
3341
- name: Health Check PostService
3442
run: |

.github/workflows/file.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: File Service CI/CD Pipeline
2+
3+
on:
4+
push:
5+
paths:
6+
- backend/src/**
7+
- .github/workflows/file.yml
8+
branches:
9+
- master
10+
- develop
11+
tags:
12+
- 'v*'
13+
pull_request:
14+
types: [opened, synchronize, reopened]
15+
16+
jobs:
17+
build-and-test:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Run reusable Build and Test action
25+
uses: ./.github/actions/build-and-test
26+
with:
27+
backendCsprojPath: ./backend/src/FileService/FileService.Api/FileService.Api.csproj
28+
# unitTestsProjectPath: ./backend/tests/FileService/FileService.Domain.Tests/FileService.Domain.Tests.csproj
29+
buildConfiguration: Release
30+
serviceName: FileService
31+
32+
docker:
33+
needs: build-and-test
34+
runs-on: ubuntu-latest
35+
36+
steps:
37+
- name: Checkout repository
38+
uses: actions/checkout@v4
39+
40+
- name: Log in to Docker Hub
41+
run: echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin
42+
43+
- name: Build Docker image
44+
run: |
45+
IMAGE_VERSION="latest"
46+
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
47+
IMAGE_VERSION=${GITHUB_REF#refs/tags/}
48+
fi
49+
docker buildx build \
50+
-t ${{ secrets.DOCKER_HUB_USERNAME }}/file-service:${IMAGE_VERSION} \
51+
-f ./backend/src/FileService/Dockerfile \
52+
./backend/src
53+
54+
- name: Push Docker image to Docker Hub
55+
if: startsWith(github.ref, 'refs/tags/')
56+
run: |
57+
IMAGE_VERSION=${GITHUB_REF#refs/tags/}
58+
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/file-service:${IMAGE_VERSION}

FitnessApp.sln

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
6565
.github\workflows\compose-build.yml = .github\workflows\compose-build.yml
6666
.github\workflows\frontend.yml = .github\workflows\frontend.yml
6767
.github\workflows\post.yml = .github\workflows\post.yml
68+
.github\workflows\file.yml = .github\workflows\file.yml
6869
EndProjectSection
6970
EndProject
7071
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "actions", "actions", "{499BA3B4-A81F-4079-B256-CC04927BB06D}"
@@ -83,6 +84,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gateway", "backend\src\Gate
8384
EndProject
8485
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gateway", "backend\src\Gateway\Gateway\Gateway.csproj", "{830B4F05-7C89-4C0F-B27D-B1008B605E79}"
8586
EndProject
87+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileService", "FileService", "{43F219C3-D6F8-4BA4-890D-4411CCEA3034}"
88+
ProjectSection(SolutionItems) = preProject
89+
backend\src\FileService\Dockerfile = backend\src\FileService\Dockerfile
90+
EndProjectSection
91+
EndProject
92+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileService.Api", "backend\src\FileService\FileService.Api\FileService.Api.csproj", "{A42D3D0A-750D-4E69-ACD5-751D64BC50E9}"
93+
EndProject
94+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileService.Domain", "backend\src\FileService\FileService.Domain\FileService.Domain.csproj", "{757BB459-C6FF-4286-BF77-BBA57C201731}"
95+
EndProject
96+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileService.Application", "backend\src\FileService\FileService.Application\FileService.Application.csproj", "{222CCDC4-3D79-4954-B7E0-736D474270D6}"
97+
EndProject
98+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileService.Persistence", "backend\src\FileService\FileService.Persistence\FileService.Persistence.csproj", "{2F748171-33D6-484F-924C-21539C87483E}"
99+
EndProject
100+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileService.Infrastructure", "backend\src\FileService\FileService.Infrastructure\FileService.Infrastructure.csproj", "{4938EBCD-F47E-4ABF-AD79-A5DEB42341DA}"
101+
EndProject
86102
Global
87103
GlobalSection(SolutionConfigurationPlatforms) = preSolution
88104
Debug|Any CPU = Debug|Any CPU
@@ -153,6 +169,26 @@ Global
153169
{830B4F05-7C89-4C0F-B27D-B1008B605E79}.Debug|Any CPU.Build.0 = Debug|Any CPU
154170
{830B4F05-7C89-4C0F-B27D-B1008B605E79}.Release|Any CPU.ActiveCfg = Release|Any CPU
155171
{830B4F05-7C89-4C0F-B27D-B1008B605E79}.Release|Any CPU.Build.0 = Release|Any CPU
172+
{A42D3D0A-750D-4E69-ACD5-751D64BC50E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
173+
{A42D3D0A-750D-4E69-ACD5-751D64BC50E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
174+
{A42D3D0A-750D-4E69-ACD5-751D64BC50E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
175+
{A42D3D0A-750D-4E69-ACD5-751D64BC50E9}.Release|Any CPU.Build.0 = Release|Any CPU
176+
{757BB459-C6FF-4286-BF77-BBA57C201731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
177+
{757BB459-C6FF-4286-BF77-BBA57C201731}.Debug|Any CPU.Build.0 = Debug|Any CPU
178+
{757BB459-C6FF-4286-BF77-BBA57C201731}.Release|Any CPU.ActiveCfg = Release|Any CPU
179+
{757BB459-C6FF-4286-BF77-BBA57C201731}.Release|Any CPU.Build.0 = Release|Any CPU
180+
{222CCDC4-3D79-4954-B7E0-736D474270D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
181+
{222CCDC4-3D79-4954-B7E0-736D474270D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
182+
{222CCDC4-3D79-4954-B7E0-736D474270D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
183+
{222CCDC4-3D79-4954-B7E0-736D474270D6}.Release|Any CPU.Build.0 = Release|Any CPU
184+
{2F748171-33D6-484F-924C-21539C87483E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
185+
{2F748171-33D6-484F-924C-21539C87483E}.Debug|Any CPU.Build.0 = Debug|Any CPU
186+
{2F748171-33D6-484F-924C-21539C87483E}.Release|Any CPU.ActiveCfg = Release|Any CPU
187+
{2F748171-33D6-484F-924C-21539C87483E}.Release|Any CPU.Build.0 = Release|Any CPU
188+
{4938EBCD-F47E-4ABF-AD79-A5DEB42341DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
189+
{4938EBCD-F47E-4ABF-AD79-A5DEB42341DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
190+
{4938EBCD-F47E-4ABF-AD79-A5DEB42341DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
191+
{4938EBCD-F47E-4ABF-AD79-A5DEB42341DA}.Release|Any CPU.Build.0 = Release|Any CPU
156192
EndGlobalSection
157193
GlobalSection(NestedProjects) = preSolution
158194
{2E44C019-ED30-4671-A878-D2F7B6071024} = {84AE3F00-9A59-4A8D-A737-67AB74E5D1FD}
@@ -180,5 +216,11 @@ Global
180216
{334DF17C-BD69-47B9-B4D0-ACB5AD6223CF} = {112E9C63-BF62-49C1-AD19-03855535225B}
181217
{DC9B9F00-24BF-4AD3-B45A-38BFCFC309D7} = {B7E4E4CF-E7A9-4DAC-807E-DFF17553BAE8}
182218
{830B4F05-7C89-4C0F-B27D-B1008B605E79} = {DC9B9F00-24BF-4AD3-B45A-38BFCFC309D7}
219+
{43F219C3-D6F8-4BA4-890D-4411CCEA3034} = {B7E4E4CF-E7A9-4DAC-807E-DFF17553BAE8}
220+
{A42D3D0A-750D-4E69-ACD5-751D64BC50E9} = {43F219C3-D6F8-4BA4-890D-4411CCEA3034}
221+
{757BB459-C6FF-4286-BF77-BBA57C201731} = {43F219C3-D6F8-4BA4-890D-4411CCEA3034}
222+
{222CCDC4-3D79-4954-B7E0-736D474270D6} = {43F219C3-D6F8-4BA4-890D-4411CCEA3034}
223+
{2F748171-33D6-484F-924C-21539C87483E} = {43F219C3-D6F8-4BA4-890D-4411CCEA3034}
224+
{4938EBCD-F47E-4ABF-AD79-A5DEB42341DA} = {43F219C3-D6F8-4BA4-890D-4411CCEA3034}
183225
EndGlobalSection
184226
EndGlobal

backend/src/FileService/Dockerfile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
2+
WORKDIR /app
3+
EXPOSE 8004
4+
5+
RUN apt-get update && apt-get install -y curl && apt-get clean
6+
7+
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
8+
9+
WORKDIR /src
10+
11+
COPY FileService/FileService.Api/FileService.Api.csproj FileService/FileService.Api/
12+
COPY FileService/FileService.Application/FileService.Application.csproj FileService/FileService.Application/
13+
COPY FileService/FileService.Domain/FileService.Domain.csproj FileService/FileService.Domain/
14+
COPY FileService/FileService.Infrastructure/FileService.Infrastructure.csproj FileService/FileService.Infrastructure/
15+
COPY FileService/FileService.Persistence/FileService.Persistence.csproj FileService/FileService.Persistence/
16+
COPY Shared/Shared.Application/Shared.Application.csproj Shared/Shared.Application/
17+
COPY Shared/Shared.DTO/Shared.DTO.csproj Shared/Shared.DTO/
18+
19+
RUN dotnet restore FileService/FileService.Api/FileService.Api.csproj
20+
21+
COPY . .
22+
23+
WORKDIR /src/FileService/FileService.Api
24+
25+
RUN dotnet build FileService.Api.csproj -c Release -o /app/build
26+
27+
FROM build AS publish
28+
RUN dotnet publish FileService.Api.csproj -c Release -o /app/publish
29+
30+
FROM base AS final
31+
WORKDIR /app
32+
COPY --from=publish /app/publish .
33+
34+
ENTRYPOINT ["dotnet", "FileService.Api.dll"]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0">
11+
<PrivateAssets>all</PrivateAssets>
12+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13+
</PackageReference>
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\FileService.Application\FileService.Application.csproj" />
18+
<ProjectReference Include="..\FileService.Infrastructure\FileService.Infrastructure.csproj" />
19+
<ProjectReference Include="..\FileService.Persistence\FileService.Persistence.csproj" />
20+
</ItemGroup>
21+
22+
</Project>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using FileService.Application;
2+
using FileService.Domain.Constants;
3+
using FileService.Infrastructure;
4+
using FileService.Persistence;
5+
using Microsoft.EntityFrameworkCore;
6+
7+
var builder = WebApplication.CreateBuilder(args);
8+
9+
var hostingUrl = builder.Configuration[AppSettingsConstants.WebHostUrl];
10+
11+
builder.WebHost.UseUrls(hostingUrl ?? throw new ArgumentNullException(nameof(hostingUrl), "Hosting URL is not configured."));
12+
13+
builder.Services
14+
.AddPersistenceServices(builder.Configuration)
15+
.AddInfrastructureServices(builder.Configuration)
16+
.AddApplicationServices();
17+
18+
var app = builder.Build();
19+
20+
using (var scope = app.Services.CreateScope())
21+
{
22+
var dbContext = scope.ServiceProvider.GetRequiredService<FileDbContext>();
23+
dbContext.Database.Migrate();
24+
}
25+
26+
app.MapGet("/health", () => Results.Ok("Healthy"));
27+
28+
app.Run();
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"$schema": "http://json.schemastore.org/launchsettings.json",
3+
"iisSettings": {
4+
"windowsAuthentication": false,
5+
"anonymousAuthentication": true,
6+
"iisExpress": {
7+
"applicationUrl": "http://localhost:13401",
8+
"sslPort": 44319
9+
}
10+
},
11+
"profiles": {
12+
"http": {
13+
"commandName": "Project",
14+
"dotnetRunMessages": true,
15+
"launchBrowser": true,
16+
"launchUrl": "graphql",
17+
"applicationUrl": "http://localhost:8004",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
},
22+
"https": {
23+
"commandName": "Project",
24+
"dotnetRunMessages": true,
25+
"launchBrowser": true,
26+
"launchUrl": "graphql",
27+
"applicationUrl": "https://localhost:7144;http://localhost:8004",
28+
"environmentVariables": {
29+
"ASPNETCORE_ENVIRONMENT": "Development"
30+
}
31+
},
32+
"IIS Express": {
33+
"commandName": "IISExpress",
34+
"launchBrowser": true,
35+
"launchUrl": "swagger",
36+
"environmentVariables": {
37+
"ASPNETCORE_ENVIRONMENT": "Development"
38+
}
39+
}
40+
}
41+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*",
9+
"WebHostUrl": "http://0.0.0.0:8004",
10+
"ConnectionStrings": {
11+
"DatabaseConnectionString": "Host=localhost;Port=5432;Username=postgres;Password=mysecretpasswordfordevelopment;Database=FileDb",
12+
"AzureStorageConnectionString": "AccountName=sentemon;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=https;BlobEndpoint=https://localhost:10000/sentemon"
13+
}
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace FileService.Application;
4+
5+
public static class DependencyInjection
6+
{
7+
public static IServiceCollection AddApplicationServices(this IServiceCollection services)
8+
{
9+
return services;
10+
}
11+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
11+
</ItemGroup>
12+
13+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace FileService.Domain.Constants;
2+
3+
public static class AppSettingsConstants
4+
{
5+
public const string WebHostUrl = "WebHostUrl";
6+
public const string DatabaseConnectionString = "DatabaseConnectionString";
7+
public const string AzureStorageConnectionString = "AzureStorageConnectionString";
8+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace FileService.Domain.Entities;
2+
3+
public class File
4+
{
5+
public Guid Id { get; private set; }
6+
public string Name { get; private set; }
7+
public string BlobName { get; private set; }
8+
public long Size { get; private set; }
9+
public string OwnerId { get; private set; }
10+
public DateTime CreatedAt { get; private set; }
11+
12+
private File(string name, string blobName, long size, string ownerId)
13+
{
14+
Name = name;
15+
BlobName = blobName;
16+
Size = size;
17+
OwnerId = ownerId;
18+
}
19+
20+
public static File CreateFile(string name, string blobName, long size, string ownerId)
21+
{
22+
return new File(name, blobName, size, ownerId);
23+
}
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
</Project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Azure.Storage.Blobs;
2+
using FileService.Domain.Constants;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.DependencyInjection;
5+
6+
namespace FileService.Infrastructure;
7+
8+
public static class DependencyInjection
9+
{
10+
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
11+
{
12+
var azureStorageConnectionString = configuration.GetConnectionString(AppSettingsConstants.AzureStorageConnectionString);
13+
14+
services.AddSingleton(new BlobServiceClient(azureStorageConnectionString));
15+
16+
return services;
17+
}
18+
}

0 commit comments

Comments
 (0)