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
37 changes: 37 additions & 0 deletions .github/actions/build-dotnet/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: build-dotnet
description: ".NET restore + build"

inputs:
project-dir:
description: "Project working directory"
required: true

runs:
using: composite
steps:
- name: Setup .NET SDK (from global.json)
uses: actions/setup-dotnet@v4
with:
global-json-file: '${{ inputs.project-dir }}/global.json'

- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles(format('{0}/**/*.csproj', inputs.project-dir), format('{0}/global.json', inputs.project-dir)) }}
restore-keys: ${{ runner.os }}-nuget-

- name: Clean Release
run: dotnet clean --configuration Release
shell: bash
working-directory: ${{ inputs.project-dir }}

- name: Restore
run: dotnet restore
shell: bash
working-directory: ${{ inputs.project-dir }}

- name: Build Release (warnings as errors)
run: dotnet build --configuration Release --no-restore -warnaserror
shell: bash
working-directory: ${{ inputs.project-dir }}
31 changes: 31 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Manual Deployment

on:
workflow_dispatch:
inputs:
image_tag:
description: 'Tag to deploy'
required: true
default: 'latest'

env:
REGISTRY: ghcr.io
IMAGE_NAME: goodman74/asp.net.otus

jobs:
cd-main-deploy:
runs-on: ubuntu-latest
steps:
- name: Pull image
run: docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ inputs.image_tag }}

- name: Run container
run: docker run -d -p 8080:8080 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event.inputs.image_tag }}

- name: Health check
run: |
for i in {1..20}; do
curl -f http://localhost:8080/api/v1/roles && exit 0
sleep 1
done
exit 1
91 changes: 91 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Build, Test, Publish Image

on:
push:
branches: [main]
paths:
- 'Homeworks/06 Настройка CI/**'

concurrency:
group: ci-main
cancel-in-progress: false

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
PROJECT_DIR: 'Homeworks/06 Настройка CI/src'

permissions:
contents: read
packages: write

jobs:
build-test-push:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ env.PROJECT_DIR }}

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

- name: Check working directory
run: pwd

- name: Build-dotnet
uses: ./.github/actions/build-dotnet
with:
project-dir: ${{ env.PROJECT_DIR }}

- name: Run tests
run: |
dotnet test --configuration Release --no-build --no-restore --collect:"XPlat Code Coverage" \
--settings "PromoCodeFactory.UnitTests/coverage.runsettings" --logger "trx"

- name: Generate HTML Coverage Report
uses: danielpalme/ReportGenerator-GitHub-Action@5
with:
reports: '${{ env.PROJECT_DIR }}/*/TestResults/*/coverage.cobertura.xml'
targetdir: '${{ env.PROJECT_DIR }}/coveragereport'
reporttypes: 'Html'

- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-html
path: '${{ env.PROJECT_DIR }}/coveragereport/'

- name: Publish test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: '${{ env.PROJECT_DIR }}/*/TestResults/*.trx'

- name: Log in to container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha
type=ref,event=branch
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: '${{ env.PROJECT_DIR }}'
file: '${{ env.PROJECT_DIR }}/Dockerfile.ci'
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
22 changes: 22 additions & 0 deletions .github/workflows/clean-ghcr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Cleanup GHCR

on:
workflow_dispatch:
schedule:
- cron: '0 3 * * 0'

permissions:
packages: write
contents: read

jobs:
cleanup:
runs-on: ubuntu-latest

steps:
- name: Keep last 5 images (prune others)
uses: actions/delete-package-versions@v5
with:
package-name: asp.net.otus
package-type: container
min-versions-to-keep: 5
8 changes: 3 additions & 5 deletions Homeworks/06 Настройка CI/src/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
**/values.dev.yaml
LICENSE
README.md
!**/.gitignore
!.git/HEAD
!.git/config
!.git/packed-refs
!.git/refs/heads/**
# Исключаем локальные артефакты (если есть)
**/publish/
**/TestResults/
38 changes: 31 additions & 7 deletions Homeworks/06 Настройка CI/src/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG DOTNET_VERSION=10.0
# -------- base runtime --------
FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION} AS base
WORKDIR /app
EXPOSE 8080

# ---------- build ----------
FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY . .
# скопировать файлы, которые управляют restore (чтобы улучшить кеш restore)
COPY ./global.json ./
COPY ./*.sln* ./
COPY ./PromoCodeFactory.Core/PromoCodeFactory.Core.csproj ./PromoCodeFactory.Core/
COPY ./PromoCodeFactory.DataAccess/PromoCodeFactory.DataAccess.csproj ./PromoCodeFactory.DataAccess/
COPY ./PromoCodeFactory.WebHost/PromoCodeFactory.WebHost.csproj ./PromoCodeFactory.WebHost/
COPY ./PromoCodeFactory.UnitTests/PromoCodeFactory.UnitTests.csproj ./PromoCodeFactory.UnitTests/

RUN dotnet restore

# теперь весь код
COPY ./PromoCodeFactory.Core/ ./PromoCodeFactory.Core/
COPY ./PromoCodeFactory.DataAccess/ ./PromoCodeFactory.DataAccess/
COPY ./PromoCodeFactory.WebHost/ ./PromoCodeFactory.WebHost/
COPY ./PromoCodeFactory.UnitTests/ ./PromoCodeFactory.UnitTests/

RUN dotnet build -c $BUILD_CONFIGURATION --no-restore

FROM build AS publish
# ---------- test ----------
FROM build AS test
RUN dotnet test --no-build --no-restore -c Release --collect:"XPlat Code Coverage" --settings PromoCodeFactory.UnitTests/coverage.runsettings \
--logger "trx" --results-directory /test-results

# ---------- publish ----------
FROM test AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish ./PromoCodeFactory.WebHost/PromoCodeFactory.WebHost.csproj \
-c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false --no-build
-c $BUILD_CONFIGURATION -o /app/publish --no-build --no-restore

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
WORKDIR /app
FROM base AS final
COPY --from=publish /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "PromoCodeFactory.WebHost.dll"]
36 changes: 36 additions & 0 deletions Homeworks/06 Настройка CI/src/Dockerfile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
ARG DOTNET_VERSION=10.0
# -------- base runtime --------
FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION} AS base
WORKDIR /app
EXPOSE 8080

# ---------- build ----------
FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
# скопировать файлы, которые управляют restore (чтобы улучшить кеш restore)
COPY ./global.json ./
COPY ./*.sln* ./
COPY ./PromoCodeFactory.Core/PromoCodeFactory.Core.csproj ./PromoCodeFactory.Core/
COPY ./PromoCodeFactory.DataAccess/PromoCodeFactory.DataAccess.csproj ./PromoCodeFactory.DataAccess/
COPY ./PromoCodeFactory.WebHost/PromoCodeFactory.WebHost.csproj ./PromoCodeFactory.WebHost/
COPY ./PromoCodeFactory.UnitTests/PromoCodeFactory.UnitTests.csproj ./PromoCodeFactory.UnitTests/

RUN dotnet restore

# теперь весь код
COPY ./PromoCodeFactory.Core/ ./PromoCodeFactory.Core/
COPY ./PromoCodeFactory.DataAccess/ ./PromoCodeFactory.DataAccess/
COPY ./PromoCodeFactory.WebHost/ ./PromoCodeFactory.WebHost/
COPY ./PromoCodeFactory.UnitTests/ ./PromoCodeFactory.UnitTests/

RUN dotnet build -c $BUILD_CONFIGURATION --no-restore

# ---------- publish ----------
FROM build AS publish
RUN dotnet publish ./PromoCodeFactory.WebHost/PromoCodeFactory.WebHost.csproj \
-c $BUILD_CONFIGURATION -o /app/publish --no-build --no-restore

FROM base AS final
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "PromoCodeFactory.WebHost.dll"]
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
Expand All @@ -10,7 +10,7 @@
<ItemGroup>
<PackageReference Include="AwesomeAssertions" Version="9.4.0" />
<PackageReference Include="Bogus" Version="35.6.5" />
<PackageReference Include="coverlet.collector" Version="8.0.0">
<PackageReference Include="coverlet.collector" Version="10.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="XPlat Code Coverage">
<Configuration>

<!-- Формат -->
<Format>cobertura</Format>

<!-- Исключаем мусор -->
<ExcludeByFile>**/obj/**,**/bin/**,**/*.g.cs,**/*.generated.cs</ExcludeByFile>

<!-- (опционально) исключение по namespace/типам -->
<Exclude>
[*]Program
</Exclude>

</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: HW06_promocode
services:
promocode-factory-api:
build: src/
build:
context: .
container_name: 'promocode-factory-api'
restart: always
ports:
Expand All @@ -10,6 +12,6 @@ services:
environment:
- "ConnectionStrings:PromocodeFactoryDb=Filename=/app/db/PromoCodeFactoryDb.sqlite"
- "ASPNETCORE_ENVIRONMENT=Development"

volumes:
db:
db:
30 changes: 30 additions & 0 deletions Homeworks/06 Настройка CI/src/docker-compose.test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: HW06_promocode_GHCR
services:
promocode-factory-api_ghcr:
image: ghcr.io/goodman74/asp.net.otus:latest
#container_name: 'promocode-factory-api-ghcr'
restart: always
ports:
- "8099:8080"
volumes:
- db:/app/db
environment:
- "ConnectionStrings:PromocodeFactoryDb=Filename=/app/db/PromoCodeFactoryDb.sqlite"
- "ASPNETCORE_ENVIRONMENT=Development"

smoke:
image: curlimages/curl:latest
depends_on:
- promocode-factory-api_ghcr
command: >
sh -c "
echo 'Waiting before smoke test 5 sec ...';
sleep 5;
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20;
do curl -f http://promocode-factory-api_ghcr:8080/api/v1/roles && exit 0;
sleep 1;
done;
exit 1"

volumes:
db:
6 changes: 6 additions & 0 deletions Homeworks/06 Настройка CI/src/global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"sdk": {
"version": "10.0.201",
"rollForward": "latestFeature"
}
}