Skip to content

deps: Bump Grpc.Tools and Microsoft.SourceLink.GitHub #641

deps: Bump Grpc.Tools and Microsoft.SourceLink.GitHub

deps: Bump Grpc.Tools and Microsoft.SourceLink.GitHub #641

Workflow file for this run

name: CI/CD Pipeline
on:
push:
branches: [ master, develop ]
tags: [ 'v*' ]
pull_request:
branches: [ master, develop ]
permissions:
contents: read
packages: write
env:
DOTNET_VERSION: '10.0.x'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_NOLOGO: true
CI_TEST_FILTER: 'Category!=Debug&Category!=Manual'
MIN_LINE_COVERAGE_PERCENT: '18'
jobs:
build:
name: Build & Test
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Display .NET info
run: dotnet --info
- name: Restore dependencies
run: dotnet restore SharpCoreDB.CI.slnf --configfile NuGet.Config /p:UseLocalProjectReferences=true
- name: Fail on deprecated NuGet packages
shell: pwsh
run: |
$output = dotnet list SharpCoreDB.CI.slnf package --deprecated --configfile NuGet.Config
$outputText = $output | Out-String
Write-Host $outputText
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to evaluate deprecated packages."
exit $LASTEXITCODE
}
if ($outputText -match "has the following deprecated packages") {
Write-Error "Deprecated NuGet packages detected. CI is configured to fail."
exit 1
}
Write-Host "No deprecated NuGet packages detected."
- name: Fail on vulnerable NuGet packages
shell: pwsh
run: |
$output = dotnet list SharpCoreDB.CI.slnf package --vulnerable --configfile NuGet.Config
$outputText = $output | Out-String
Write-Host $outputText
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to evaluate vulnerable packages."
exit $LASTEXITCODE
}
if ($outputText -match "has the following vulnerable packages") {
Write-Error "Vulnerable NuGet packages detected. CI is configured to fail."
exit 1
}
Write-Host "No vulnerable NuGet packages detected."
- name: Build
run: dotnet build SharpCoreDB.CI.slnf --configuration Release --no-restore /p:ContinuousIntegrationBuild=true /p:UseLocalProjectReferences=true
- name: Test SharpCoreDB.Tests
run: dotnet test tests/SharpCoreDB.Tests/SharpCoreDB.Tests.csproj --configuration Release --no-build --verbosity minimal --logger trx --results-directory ./TestResults/SharpCoreDB.Tests --collect:"XPlat Code Coverage" --filter "${{ env.CI_TEST_FILTER }}" --blame-hang --blame-hang-timeout 10m -- RunConfiguration.TestSessionTimeout=600000
timeout-minutes: 30
env:
CI: "true"
GITHUB_ACTIONS: "true"
- name: Test SharpCoreDB.VectorSearch.Tests
run: dotnet test tests/SharpCoreDB.VectorSearch.Tests/SharpCoreDB.VectorSearch.Tests.csproj --configuration Release --no-build --verbosity minimal --logger trx --results-directory ./TestResults/SharpCoreDB.VectorSearch.Tests --collect:"XPlat Code Coverage" --filter "${{ env.CI_TEST_FILTER }}" --blame-hang --blame-hang-timeout 10m -- RunConfiguration.TestSessionTimeout=600000
timeout-minutes: 15
env:
CI: "true"
GITHUB_ACTIONS: "true"
- name: Validate coverage threshold
if: matrix.os == 'ubuntu-latest'
shell: python3 {0}
run: |
import glob
import os
import sys
import xml.etree.ElementTree as ET
threshold = float(os.environ.get("MIN_LINE_COVERAGE_PERCENT", "60"))
files = glob.glob("**/TestResults/**/coverage.cobertura.xml", recursive=True)
if not files:
print("No coverage.cobertura.xml files found.", file=sys.stderr)
sys.exit(1)
covered = 0
valid = 0
for file in files:
try:
root = ET.parse(file).getroot()
lines_valid = int(root.attrib.get("lines-valid", "0"))
lines_covered = int(root.attrib.get("lines-covered", "0"))
valid += lines_valid
covered += lines_covered
print(f"Coverage input: {file} -> {lines_covered}/{lines_valid}")
except Exception as ex:
print(f"Skipping unreadable coverage file {file}: {ex}")
if valid == 0:
print("Coverage reports found but lines-valid is 0.", file=sys.stderr)
sys.exit(1)
percent = (covered / valid) * 100.0
print(f"Merged line coverage: {percent:.2f}% (threshold: {threshold:.2f}%)")
if percent < threshold:
print("Coverage threshold not met.", file=sys.stderr)
sys.exit(1)
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}
path: '**/TestResults/**/*.trx'
if-no-files-found: ignore
- name: Upload coverage
if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v6
with:
files: '**/TestResults/**/coverage.cobertura.xml'
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
pack:
name: Pack NuGet Packages
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Pack NuGet packages
run: dotnet pack SharpCoreDB.CI.slnf --configuration Release --output ./artifacts /p:ContinuousIntegrationBuild=true /p:UseLocalProjectReferences=true --configfile NuGet.Config
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: nuget-packages
path: ./artifacts/*.nupkg
retention-days: 30
publish:
name: Publish to NuGet.org
runs-on: ubuntu-latest
needs: pack
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
steps:
- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Download NuGet packages
uses: actions/download-artifact@v4
with:
name: nuget-packages
path: ./artifacts
- name: Publish packages in dependency order
shell: bash
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
NUGET_SOURCE: https://api.nuget.org/v3/index.json
run: |
set -euo pipefail
push_layer() {
local layer_name="$1"
shift
local found_any=false
echo "::group::Publishing $layer_name"
for pattern in "$@"; do
for pkg in ./artifacts/${pattern}; do
[ -f "$pkg" ] || continue
found_any=true
echo " ↗ Pushing $(basename "$pkg")"
dotnet nuget push "$pkg" \
--api-key "$NUGET_API_KEY" \
--source "$NUGET_SOURCE" \
--skip-duplicate || true
done
done
echo "::endgroup::"
# Wait for NuGet.org indexing before pushing the next layer
if [ "$found_any" = true ]; then
echo "⏳ Waiting 30s for NuGet.org to index $layer_name..."
sleep 30
fi
}
# Layer 0 – no internal dependencies
push_layer "Layer 0 (core)" \
"SharpCoreDB.[0-9]*.nupkg" \
"SharpCoreDB.Client.Protocol.*.nupkg" \
"SharpCoreDB.Server.Protocol.*.nupkg"
# Layer 1 – depends on core only
push_layer "Layer 1 (core dependents)" \
"SharpCoreDB.Graph.[0-9]*.nupkg" \
"SharpCoreDB.VectorSearch.*.nupkg" \
"SharpCoreDB.Functional.[0-9]*.nupkg" \
"SharpCoreDB.EventSourcing.*.nupkg" \
"SharpCoreDB.Analytics.*.nupkg" \
"SharpCoreDB.Distributed.*.nupkg" \
"SharpCoreDB.Identity.*.nupkg" \
"SharpCoreDB.Serilog.Sinks.*.nupkg"
# Layer 2 – depends on layer 1
push_layer "Layer 2 (mid-level)" \
"SharpCoreDB.Client.[0-9]*.nupkg" \
"SharpCoreDB.EntityFrameworkCore.[0-9]*.nupkg" \
"SharpCoreDB.Extensions.*.nupkg" \
"SharpCoreDB.Data.Provider.*.nupkg" \
"SharpCoreDB.Server.Core.*.nupkg" \
"SharpCoreDB.CQRS.*.nupkg" \
"SharpCoreDB.Projections.*.nupkg"
# Layer 3 – depends on layer 2
push_layer "Layer 3 (top-level)" \
"SharpCoreDB.Server.[0-9]*.nupkg" \
"SharpCoreDB.Graph.Advanced.*.nupkg" \
"SharpCoreDB.Provider.Sync.*.nupkg" \
"SharpCoreDB.Provider.YesSql.*.nupkg" \
"SharpCoreDB.Functional.Dapper.*.nupkg" \
"SharpCoreDB.Functional.EntityFrameworkCore.*.nupkg"
# Catch any remaining packages not in the layers above
push_layer "Remaining packages" \
"*.nupkg"
echo "✅ All packages published in dependency order."
- name: Create release summary
run: |
echo "## 📦 NuGet Packages Published (Dependency-Ordered)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Published $(ls -1 ./artifacts/*.nupkg | wc -l) package(s) to NuGet.org" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Packages were published in 4 layers based on their dependency chain," >> $GITHUB_STEP_SUMMARY
echo "with 30-second waits between layers for NuGet.org indexing." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Packages" >> $GITHUB_STEP_SUMMARY
ls -1 ./artifacts/*.nupkg | xargs -I {} basename {} >> $GITHUB_STEP_SUMMARY