1+ # Reusable workflow for building and testing .NET projects
2+ # This workflow can be called from other repositories to standardize CI/CD
3+ name : .NET Build and Test
4+
5+ on :
6+ workflow_call :
7+ inputs :
8+ # Path to the solution file relative to repository root
9+ solution-path :
10+ description : ' Path to the .sln file'
11+ required : false
12+ type : string
13+ default : ' **/*.sln'
14+
15+ # .NET SDK version to use
16+ dotnet-version :
17+ description : ' .NET SDK version'
18+ required : false
19+ type : string
20+ default : ' 8.0.x'
21+
22+ # Pattern to find test projects
23+ test-projects :
24+ description : ' Pattern to find test projects'
25+ required : false
26+ type : string
27+ default : ' **/*Tests.csproj'
28+
29+ # Build configuration (Debug/Release)
30+ build-configuration :
31+ description : ' Build configuration'
32+ required : false
33+ type : string
34+ default : ' Release'
35+
36+ # Whether to run tests
37+ run-tests :
38+ description : ' Run tests'
39+ required : false
40+ type : boolean
41+ default : true
42+
43+ # Whether to upload test results
44+ upload-test-results :
45+ description : ' Upload test results'
46+ required : false
47+ type : boolean
48+ default : true
49+
50+ # Whether to upload code coverage
51+ upload-coverage :
52+ description : ' Upload code coverage'
53+ required : false
54+ type : boolean
55+ default : false
56+
57+ jobs :
58+ build-and-test :
59+ runs-on : ubuntu-latest
60+
61+ steps :
62+ # Checkout the repository code
63+ - name : Checkout code
64+ uses : actions/checkout@v4
65+ with :
66+ fetch-depth : 0 # Full history for better analysis
67+
68+ # Setup .NET SDK with specified version
69+ - name : Setup .NET
70+ uses : actions/setup-dotnet@v4
71+ with :
72+ dotnet-version : ${{ inputs.dotnet-version }}
73+
74+ # Cache NuGet packages to speed up builds
75+ - name : Cache NuGet packages
76+ uses : actions/cache@v4
77+ with :
78+ path : ~/.nuget/packages
79+ key : ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }}
80+ restore-keys : |
81+ ${{ runner.os }}-nuget-
82+
83+ # Restore dependencies
84+ - name : Restore dependencies
85+ run : |
86+ # Find and restore all solution files matching the pattern
87+ for solution in $(find . -path "${{ inputs.solution-path }}" -type f); do
88+ echo "Restoring $solution"
89+ dotnet restore "$solution"
90+ done
91+
92+ # Build the solution
93+ - name : Build
94+ run : |
95+ # Find and build all solution files matching the pattern
96+ for solution in $(find . -path "${{ inputs.solution-path }}" -type f); do
97+ echo "Building $solution"
98+ dotnet build "$solution" \
99+ --configuration ${{ inputs.build-configuration }} \
100+ --no-restore \
101+ --verbosity normal
102+ done
103+
104+ # Run tests if enabled
105+ - name : Test
106+ if : inputs.run-tests
107+ run : |
108+ # Find all test projects and run tests
109+ test_projects=$(find . -path "${{ inputs.test-projects }}" -type f)
110+
111+ if [ -z "$test_projects" ]; then
112+ echo "No test projects found matching pattern: ${{ inputs.test-projects }}"
113+ else
114+ for project in $test_projects; do
115+ echo "Testing $project"
116+
117+ # Determine if we should collect code coverage
118+ if [ "${{ inputs.upload-coverage }}" = "true" ]; then
119+ dotnet test "$project" \
120+ --configuration ${{ inputs.build-configuration }} \
121+ --no-build \
122+ --verbosity normal \
123+ --logger "trx;LogFileName=test-results-$(basename $project .csproj).trx" \
124+ --logger "console;verbosity=detailed" \
125+ --collect:"XPlat Code Coverage" \
126+ --results-directory ./TestResults
127+ else
128+ dotnet test "$project" \
129+ --configuration ${{ inputs.build-configuration }} \
130+ --no-build \
131+ --verbosity normal \
132+ --logger "trx;LogFileName=test-results-$(basename $project .csproj).trx" \
133+ --logger "console;verbosity=detailed" \
134+ --results-directory ./TestResults
135+ fi
136+ done
137+ fi
138+
139+ # Upload test results if enabled
140+ - name : Upload test results
141+ if : inputs.upload-test-results && inputs.run-tests
142+ uses : actions/upload-artifact@v4
143+ with :
144+ name : test-results
145+ path : ./TestResults/**/*.trx
146+ retention-days : 7
147+
148+ # Upload code coverage if enabled
149+ - name : Upload coverage reports
150+ if : inputs.upload-coverage && inputs.run-tests
151+ uses : actions/upload-artifact@v4
152+ with :
153+ name : coverage-reports
154+ path : ./TestResults/**/coverage.cobertura.xml
155+ retention-days : 7
156+
157+ # Publish test results to GitHub (appears in PR checks)
158+ - name : Publish test results
159+ if : inputs.upload-test-results && inputs.run-tests && always()
160+ uses : dorny/test-reporter@v1
161+ with :
162+ name : .NET Test Results
163+ path : ' ./TestResults/**/*.trx'
164+ reporter : dotnet-trx
165+ fail-on-error : true
0 commit comments