diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..109014a --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,62 @@ +name: Portfolio CI/CD + +on: + push: + branches: [ "*" ] + tags: [ "*" ] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + container: + image: mcr.microsoft.com/dotnet/sdk:10.0 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: dotnet restore + + - name: Build Projects + run: dotnet build --configuration Release --no-restore + + test: + runs-on: ubuntu-latest + needs: build + container: + image: mcr.microsoft.com/dotnet/sdk:10.0 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Test + run: dotnet test --verbosity normal + + publish: + runs-on: ubuntu-latest + needs: build + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Pull LFS + run: git lfs pull + + - name: Login to registry + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.leon-hoppe.de \ + -u leon.hoppe --password-stdin + + - name: Build backend image + run: docker build -t git.leon-hoppe.de/leon.hoppe/portfolio/backend:latest -f src/Portfolio.Api/Dockerfile . + + - name: Build frontend image + run: docker build -t git.leon-hoppe.de/leon.hoppe/portfolio/frontend:latest -f src/Portfolio.Web/Dockerfile . + + - name: Push backend image + run: docker push git.leon-hoppe.de/leon.hoppe/portfolio/backend:latest + + - name: Push frontend image + run: docker push git.leon-hoppe.de/leon.hoppe/portfolio/frontend:latest diff --git a/src/Portfolio.Web/Services/TimelineRepository.cs b/src/Portfolio.Web/Services/TimelineRepository.cs index 1e178c1..0cdbe25 100644 --- a/src/Portfolio.Web/Services/TimelineRepository.cs +++ b/src/Portfolio.Web/Services/TimelineRepository.cs @@ -10,7 +10,7 @@ internal sealed class TimelineRepository(IHttpClientFactory factory) : ITimeline if (!result.IsSuccessStatusCode) return []; var data = await result.Content.ReadFromJsonAsync>(ct); - return data ?? []; + return data?.OrderBy(t => t.Date) ?? Enumerable.Empty(); } public async Task> GetFeaturedTimeline(CancellationToken ct) { @@ -19,6 +19,6 @@ internal sealed class TimelineRepository(IHttpClientFactory factory) : ITimeline if (!result.IsSuccessStatusCode) return []; var data = await result.Content.ReadFromJsonAsync>(ct); - return data ?? []; + return data?.OrderBy(t => t.Date) ?? Enumerable.Empty(); } } \ No newline at end of file