Files
actions/csharp-build/action.yml
Ismo Vuorinen de40e0cdc6 refactor(csharp): migrate to native setup-dotnet caching
Replace common-cache with native caching in C# actions for better
performance and maintainability.

csharp-build changes:
- Add cache: true and cache-dependency-path to setup-dotnet
- Remove redundant common-cache step
- Simplify restore logic, remove cache-hit conditionals

csharp-publish changes:
- Add cache: true and cache-dependency-path to setup-dotnet
- Remove redundant common-cache step
- Simplify restore logic, use step-security/retry for restore

Benefits:
- Native caching is more efficient and better maintained
- Reduces common-cache dependencies from 7 to 5 actions
- setup-dotnet handles NuGet package caching automatically
- Cleaner workflow without complex conditional logic

Phase 2 complete: Reduced common-cache usage from 11 to 5 actions.
2025-11-20 13:39:05 +02:00

218 lines
7.1 KiB
YAML

# yaml-language-server: $schema=https://json.schemastore.org/github-action.json
# permissions:
# - contents: read # Required for checking out repository
---
name: C# Build
description: 'Builds and tests C# projects.'
author: 'Ismo Vuorinen'
branding:
icon: 'code'
color: 'blue'
inputs:
dotnet-version:
description: 'Version of .NET SDK to use.'
required: false
max-retries:
description: 'Maximum number of retry attempts for dotnet restore operations'
required: false
default: '3'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
build_status:
description: 'Build completion status (success/failure)'
value: ${{ steps.build.outputs.status }}
test_status:
description: 'Test execution status (success/failure/skipped)'
value: ${{ steps.test.outputs.status }}
dotnet_version:
description: 'Version of .NET SDK used'
value: ${{ steps.detect-dotnet-version.outputs.detected-version }}
artifacts_path:
description: 'Path to build artifacts'
value: '**/bin/Release/**/*'
test_results_path:
description: 'Path to test results'
value: '**/*.trx'
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta
with:
token: ${{ inputs.token || github.token }}
- name: Detect .NET SDK Version
id: detect-dotnet-version
shell: sh
env:
DEFAULT_VERSION: "${{ inputs.dotnet-version || '7.0' }}"
run: |
set -eu
# Function to validate version format
validate_version() {
version=$1
case "$version" in
[0-9]* | [0-9]*.[0-9]* | [0-9]*.[0-9]*.[0-9]*)
return 0
;;
*)
return 1
;;
esac
}
# Function to clean version string
clean_version() {
printf '%s' "$1" | sed 's/^[vV]//' | tr -d ' \n\r'
}
detected_version=""
# Parse .tool-versions file
if [ -f .tool-versions ]; then
echo "Checking .tool-versions for dotnet..." >&2
version=$(awk '/^dotnet[[:space:]]/ {gsub(/#.*/, ""); print $2; exit}' .tool-versions 2>/dev/null || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found .NET version in .tool-versions: $version" >&2
detected_version="$version"
fi
fi
fi
# Parse Dockerfile
if [ -z "$detected_version" ] && [ -f Dockerfile ]; then
echo "Checking Dockerfile for dotnet..." >&2
version=$(grep -iF "FROM" Dockerfile | grep -F "dotnet:" | head -1 | \
sed -n -E "s/.*dotnet:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found .NET version in Dockerfile: $version" >&2
detected_version="$version"
fi
fi
fi
# Parse devcontainer.json
if [ -z "$detected_version" ] && [ -f .devcontainer/devcontainer.json ]; then
echo "Checking devcontainer.json for dotnet..." >&2
if command -v jq >/dev/null 2>&1; then
version=$(jq -r '.image // empty' .devcontainer/devcontainer.json 2>/dev/null | sed -n -E "s/.*dotnet:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found .NET version in devcontainer: $version" >&2
detected_version="$version"
fi
fi
else
echo "jq not found; skipping devcontainer.json parsing" >&2
fi
fi
# Parse global.json
if [ -z "$detected_version" ] && [ -f global.json ]; then
echo "Checking global.json..." >&2
if command -v jq >/dev/null 2>&1; then
version=$(jq -r '.sdk.version // empty' global.json 2>/dev/null || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found .NET version in global.json: $version" >&2
detected_version="$version"
fi
fi
else
echo "jq not found; skipping global.json parsing" >&2
fi
fi
# Use default version if nothing detected
if [ -z "$detected_version" ]; then
detected_version="$DEFAULT_VERSION"
echo "Using default .NET version: $detected_version" >&2
fi
# Set output
printf 'detected-version=%s\n' "$detected_version" >> "$GITHUB_OUTPUT"
echo "Final detected .NET version: $detected_version" >&2
- name: Setup .NET SDK
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
with:
dotnet-version: ${{ steps.detect-dotnet-version.outputs.detected-version }}
cache: true
cache-dependency-path: '**/*.csproj'
- name: Restore Dependencies
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3
with:
timeout_minutes: 10
max_attempts: ${{ inputs.max-retries }}
command: |
echo "Restoring .NET dependencies..."
dotnet restore --verbosity normal
- name: Restore Complete
shell: bash
run: |
echo "Cache hit - skipping dotnet restore"
- name: Build Solution
id: build
shell: bash
run: |
set -euo pipefail
echo "Building .NET solution..."
if dotnet build --configuration Release --no-restore --verbosity normal; then
echo "status=success" >> "$GITHUB_OUTPUT"
echo "Build completed successfully"
else
echo "status=failure" >> "$GITHUB_OUTPUT"
echo "Build failed"
exit 1
fi
- name: Run Tests
id: test
shell: bash
run: |
set -euo pipefail
echo "Running .NET tests..."
if find . -name "*.csproj" | xargs grep -lE "(Microsoft\.NET\.Test\.Sdk|xunit|nunit)" | head -1 | grep -q .; then
if dotnet test --configuration Release --no-build \
--collect:"XPlat Code Coverage" \
--logger "trx;LogFileName=test-results.trx" \
--verbosity normal; then
echo "status=success" >> "$GITHUB_OUTPUT"
echo "Tests completed successfully"
else
echo "status=failure" >> "$GITHUB_OUTPUT"
echo "Tests failed"
exit 1
fi
else
echo "No test projects found, skipping test execution."
echo "status=skipped" >> "$GITHUB_OUTPUT"
fi
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: csharp-test-results
path: |
**/*.trx
**/TestResults/**/coverage.cobertura.xml
if-no-files-found: ignore