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

on:
push:
branches: [main, master]
paths:
- 'netcore/**'
- '.github/workflows/cd.yml'
- 'netcore/Dockerfile'
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
type: choice
options:
- staging
- production

env:
DOTNET_VERSION: '6.0.x'
SOLUTION_PATH: 'netcore/SampleWebApp.NetCore.sln'
DOCKER_IMAGE_NAME: 'sample-mvc-webapp'

jobs:
build-and-test:
name: Build & Test
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

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

- name: Determine version
id: version
run: |
SHORT_SHA=$(git rev-parse --short HEAD)
VERSION="1.0.0-${SHORT_SHA}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Version: ${VERSION}"

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }}

- name: Build solution
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore

- name: Run tests
run: >
dotnet test ${{ env.SOLUTION_PATH }}
--configuration Release
--no-build
--filter "FullyQualifiedName!~PerformanceTests"
--logger "trx;LogFileName=cd-tests.trx"
--results-directory ./test-results

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: cd-test-results
path: ./test-results/
retention-days: 7

build-docker:
name: Build Docker Image
needs: build-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Build Docker image
run: |
docker build \
-f netcore/Dockerfile \
-t ${{ env.DOCKER_IMAGE_NAME }}:${{ needs.build-and-test.outputs.version }} \
-t ${{ env.DOCKER_IMAGE_NAME }}:latest \
.

- name: Test Docker image
run: |
docker run -d --name test-container -p 8080:80 ${{ env.DOCKER_IMAGE_NAME }}:latest
sleep 5
curl -f http://localhost:8080/health || echo "Health check endpoint not yet configured"
docker stop test-container
docker rm test-container

deploy-staging:
name: Deploy to Staging
needs: [build-and-test, build-docker]
runs-on: ubuntu-latest
environment:
name: staging
url: ${{ vars.STAGING_URL }}
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' || github.event.inputs.environment == 'staging'
steps:
- uses: actions/checkout@v4

- name: Deploy to staging
run: |
echo "Deploying version ${{ needs.build-and-test.outputs.version }} to staging"
echo "Image: ${{ env.DOCKER_IMAGE_NAME }}:${{ needs.build-and-test.outputs.version }}"
# Deployment commands will be configured based on hosting platform:
# - Azure App Service: az webapp deploy
# - AWS ECS: aws ecs update-service
# - Kubernetes: kubectl set image
echo "::notice::Configure deployment commands for your hosting platform"

- name: Verify staging deployment
run: |
echo "Running smoke tests against staging"
# TODO: Configure staging URL and health check verification
# curl -f ${STAGING_URL}/health

deploy-production:
name: Deploy to Production
needs: [build-and-test, build-docker, deploy-staging]
runs-on: ubuntu-latest
environment:
name: production
url: ${{ vars.PRODUCTION_URL }}
if: github.event.inputs.environment == 'production'
steps:
- uses: actions/checkout@v4

- name: Deploy to production
run: |
echo "Deploying version ${{ needs.build-and-test.outputs.version }} to production"
echo "Image: ${{ env.DOCKER_IMAGE_NAME }}:${{ needs.build-and-test.outputs.version }}"
# Deployment commands will be configured based on hosting platform
echo "::notice::Configure deployment commands for your hosting platform"

- name: Verify production deployment
run: |
echo "Running smoke tests against production"
# TODO: Configure production URL and health check verification
# curl -f ${PRODUCTION_URL}/health

- name: Tag release
run: |
git tag "v${{ needs.build-and-test.outputs.version }}"
git push origin "v${{ needs.build-and-test.outputs.version }}"
139 changes: 139 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
name: CI

on:
push:
branches: [master, main, 'release/**']
paths:
- 'netcore/**'
- '.github/workflows/ci.yml'
pull_request:
branches: [master, main, 'release/**']
paths:
- 'netcore/**'
- '.github/workflows/ci.yml'

env:
DOTNET_VERSION: '6.0.x'
SOLUTION_PATH: 'netcore/SampleWebApp.NetCore.sln'
COVERAGE_THRESHOLD: 80

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }}

- name: Build solution
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-output
path: |
netcore/src/**/bin/Release/
netcore/tests/**/bin/Release/
retention-days: 7

test:
name: Test
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }}

- name: Build solution
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore

- name: Run unit tests
run: >
dotnet test netcore/tests/SampleWebApp.UnitTests/SampleWebApp.UnitTests.csproj
--configuration Release
--no-build
--logger "trx;LogFileName=unit-tests.trx"
--results-directory ./test-results
--collect:"XPlat Code Coverage"
--settings netcore/coverlet.runsettings

- name: Run integration tests
run: >
dotnet test netcore/tests/SampleWebApp.IntegrationTests/SampleWebApp.IntegrationTests.csproj
--configuration Release
--no-build
--logger "trx;LogFileName=integration-tests.trx"
--results-directory ./test-results

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: ./test-results/
retention-days: 30

- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: ./test-results/**/coverage.cobertura.xml
retention-days: 30

- name: Install ReportGenerator
if: success()
run: dotnet tool install --global dotnet-reportgenerator-globaltool --version 5.2.5

- name: Generate coverage report
if: success()
run: >
reportgenerator
-reports:"./test-results/**/coverage.cobertura.xml"
-targetdir:"./coverage-report"
-reporttypes:"HtmlInline_AzurePipelines;Cobertura;TextSummary"

- name: Upload HTML coverage report
if: success()
uses: actions/upload-artifact@v4
with:
name: coverage-html-report
path: ./coverage-report/
retention-days: 30

- name: Check coverage threshold
if: success()
run: |
SUMMARY_FILE="./coverage-report/Summary.txt"
if [ -f "$SUMMARY_FILE" ]; then
LINE_COVERAGE=$(grep "Line coverage" "$SUMMARY_FILE" | grep -oP '[\d.]+(?=%)' | head -1)
if [ -n "$LINE_COVERAGE" ]; then
echo "Line coverage: ${LINE_COVERAGE}%"
THRESHOLD=${{ env.COVERAGE_THRESHOLD }}
if (( $(echo "$LINE_COVERAGE < $THRESHOLD" | bc -l) )); then
echo "::error::Coverage ${LINE_COVERAGE}% is below threshold ${THRESHOLD}%"
exit 1
else
echo "Coverage ${LINE_COVERAGE}% meets threshold ${THRESHOLD}%"
fi
else
echo "::warning::Could not parse coverage value"
fi
else
echo "::warning::Coverage summary file not found"
fi
95 changes: 95 additions & 0 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Code Quality

on:
push:
branches: [master, main, 'release/**']
paths:
- 'netcore/**'
- '.github/workflows/code-quality.yml'
pull_request:
branches: [master, main, 'release/**']
paths:
- 'netcore/**'
- '.github/workflows/code-quality.yml'

env:
DOTNET_VERSION: '6.0.x'
SOLUTION_PATH: 'netcore/SampleWebApp.NetCore.sln'

jobs:
format-check:
name: Code Formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }}

- name: Check code formatting
run: dotnet format ${{ env.SOLUTION_PATH }} --verify-no-changes --verbosity diagnostic

security-scan:
name: Security Scanning
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }}

- name: Run security audit
run: dotnet list ${{ env.SOLUTION_PATH }} package --vulnerable --include-transitive 2>&1 | tee security-report.txt

- name: Check for critical vulnerabilities
run: |
if grep -qi "critical\|high" security-report.txt; then
echo "::warning::Vulnerable packages detected. Review security-report.txt."
fi

- name: Upload security report
if: always()
uses: actions/upload-artifact@v4
with:
name: security-report
path: security-report.txt
retention-days: 30

build-analysis:
name: Build Warnings Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }}

- name: Build with warnings as errors
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore /warnaserror
continue-on-error: true

- name: Build with detailed warnings
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore -v detailed 2>&1 | grep -i "warning" | tee build-warnings.txt || true

- name: Upload build warnings report
if: always()
uses: actions/upload-artifact@v4
with:
name: build-warnings
path: build-warnings.txt
retention-days: 30
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,11 @@ SampleWebApp/Properties/PublishProfiles/samplemvcwebapp - Web Deploy.pubxml
SampleWebApp/Properties/PublishProfiles/samplemvcwebapp.net - WebWiz.pubxml
git/.gitattributes
git/.gitignore

# .NET Core
netcore/**/bin/
netcore/**/obj/
netcore/**/TestResults/
coverage-report/
test-results/
*.trx
Loading
Loading