@@ -3,11 +3,14 @@ name: .NET Workflow
33on :
44 push :
55 branches : [main, develop]
6- paths-ignore : ['**.md', '.github/ISSUE_TEMPLATE/**', '.github/pull_request_template.md']
6+ paths-ignore :
7+ ["**.md", ".github/ISSUE_TEMPLATE/**", ".github/pull_request_template.md"]
78 pull_request :
8- paths-ignore : ['**.md', '.github/ISSUE_TEMPLATE/**', '.github/pull_request_template.md']
9+ paths-ignore :
10+ ["**.md", ".github/ISSUE_TEMPLATE/**", ".github/pull_request_template.md"]
911 schedule :
10- - cron : " 0 23 * * *" # Daily at 11 PM UTC
12+ - cron : " 0 23 * * *" # Daily at 11 PM UTC
13+ workflow_dispatch : # Allow manual triggers
1114
1215concurrency :
1316 group : ${{ github.workflow }}-${{ github.ref }}
@@ -17,105 +20,209 @@ concurrency:
1720permissions : read-all
1821
1922env :
20- DOTNET_VERSION : ' 9.0' # Only needed for actions/setup-dotnet
23+ DOTNET_VERSION : " 9.0" # Only needed for actions/setup-dotnet
2124
2225jobs :
2326 build :
2427 name : Build, Test & Release
2528 runs-on : windows-latest
2629 timeout-minutes : 15
2730 permissions :
28- contents : write # For creating releases and committing metadata
29- packages : write # For publishing packages
31+ contents : write # For creating releases and committing metadata
32+ packages : write # For publishing packages
3033
3134 outputs :
3235 version : ${{ steps.pipeline.outputs.version }}
3336 release_hash : ${{ steps.pipeline.outputs.release_hash }}
3437 should_release : ${{ steps.pipeline.outputs.should_release }}
38+ skipped_release : ${{ steps.pipeline.outputs.skipped_release }}
3539
3640 steps :
37- - name : Checkout Repository
38- uses : actions/checkout@v4
39- with :
40- fetch-depth : 0 # Full history for versioning
41- fetch-tags : true
42- lfs : true
43- submodules : recursive
44- persist-credentials : true
45-
46- - name : Setup .NET SDK ${{ env.DOTNET_VERSION }}
47- uses : actions/setup-dotnet@v4
48- with :
49- dotnet-version : ${{ env.DOTNET_VERSION }}.x
50- cache : true
51- cache-dependency-path : ' **/*.csproj'
52-
53- - name : Run PSBuild Pipeline
54- id : pipeline
55- shell : pwsh
56- env :
57- GH_TOKEN : ${{ github.token }}
58- run : |
59- # Import the PSBuild module
60- Import-Module ${{ github.workspace }}/scripts/PSBuild.psm1
61-
62- # Get build configuration
63- $buildConfig = Get-BuildConfiguration `
64- -ServerUrl "${{ github.server_url }}" `
65- -GitRef "${{ github.ref }}" `
66- -GitSha "${{ github.sha }}" `
67- -GitHubOwner "${{ github.repository_owner }}" `
68- -GitHubRepo "${{ github.repository }}" `
69- -GithubToken "${{ github.token }}" `
70- -NuGetApiKey "${{ secrets.NUGET_KEY }}" `
71- -WorkspacePath "${{ github.workspace }}" `
72- -ExpectedOwner "ktsu-dev" `
73- -ChangelogFile "CHANGELOG.md" `
74- -AssetPatterns @("staging/*.nupkg", "staging/*.zip")
75-
76- if (-not $buildConfig.Success) {
77- throw $buildConfig.Error
78- }
79-
80- # Run the complete CI/CD pipeline
81- $result = Invoke-CIPipeline `
82- -BuildConfiguration $buildConfig.Data
83-
84- if (-not $result.Success) {
85- Write-Information "CI/CD pipeline failed: $($result.Error)" -Tags "Invoke-CIPipeline"
86- Write-Information "Stack Trace: $($result.StackTrace)" -Tags "Invoke-CIPipeline"
87- Write-Information "Build Configuration: $($buildConfig.Data | ConvertTo-Json -Depth 10)" -Tags "Invoke-CIPipeline"
88- throw $result.Error
89- }
90-
91- # Set outputs for GitHub Actions from build configuration
92- "version=$($buildConfig.Data.Version)" >> $env:GITHUB_OUTPUT
93- "release_hash=$($buildConfig.Data.ReleaseHash)" >> $env:GITHUB_OUTPUT
94- "should_release=$($buildConfig.Data.ShouldRelease)" >> $env:GITHUB_OUTPUT
95-
96- - name : Upload Coverage Report
97- uses : actions/upload-artifact@v4
98- if : always()
99- with :
100- name : coverage-report
101- path : ./coverage
102- retention-days : 7
41+ - name : Set up JDK 17
42+ uses : actions/setup-java@v4
43+ with :
44+ java-version : 17
45+ distribution : " zulu" # Alternative distribution options are available.
46+
47+ - name : Checkout Repository
48+ uses : actions/checkout@v4
49+ with :
50+ fetch-depth : 0 # Full history for versioning
51+ fetch-tags : true
52+ lfs : true
53+ submodules : recursive
54+ persist-credentials : true
55+
56+ - name : Setup .NET SDK ${{ env.DOTNET_VERSION }}
57+ uses : actions/setup-dotnet@v4
58+ with :
59+ dotnet-version : ${{ env.DOTNET_VERSION }}.x
60+ cache : true
61+ cache-dependency-path : " **/*.csproj"
62+
63+ - name : Cache SonarQube Cloud packages
64+ if : ${{ env.SONAR_TOKEN != '' }}
65+ uses : actions/cache@v4
66+ env :
67+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
68+ with :
69+ path : ~\sonar\cache
70+ key : ${{ runner.os }}-sonar
71+ restore-keys : ${{ runner.os }}-sonar
72+
73+ - name : Cache SonarQube Cloud scanner
74+ if : ${{ env.SONAR_TOKEN != '' }}
75+ id : cache-sonar-scanner
76+ uses : actions/cache@v4
77+ env :
78+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
79+ with :
80+ path : .\.sonar\scanner
81+ key : ${{ runner.os }}-sonar-scanner
82+ restore-keys : ${{ runner.os }}-sonar-scanner
83+
84+ - name : Install SonarQube Cloud scanner
85+ if : ${{ env.SONAR_TOKEN != '' && steps.cache-sonar-scanner.outputs.cache-hit != 'true' }}
86+ env :
87+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
88+ shell : powershell
89+ run : |
90+ New-Item -Path .\.sonar\scanner -ItemType Directory
91+ dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
92+
93+ - name : Begin SonarQube
94+ if : ${{ env.SONAR_TOKEN != '' }}
95+ env :
96+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
97+ shell : powershell
98+ run : |
99+ .\.sonar\scanner\dotnet-sonarscanner begin /k:"${{ github.repository_owner }}_${{ github.event.repository.name }}" /o:"${{ github.repository_owner }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="coverage/coverage.opencover.xml" /d:sonar.coverage.exclusions="**/*Test*.cs,**/*.Tests.cs,**/*.Tests/**/*,**/obj/**/*,**/*.dll" /d:sonar.cs.vstest.reportsPaths="coverage/TestResults/**/*.trx" /d:sonar.verbose=true
100+
101+ - name : Run PSBuild Pipeline
102+ id : pipeline
103+ shell : pwsh
104+ env :
105+ GH_TOKEN : ${{ github.token }}
106+ run : |
107+ # Import the PSBuild module
108+ Import-Module ${{ github.workspace }}/scripts/PSBuild.psm1
109+
110+ # Get build configuration
111+ $buildConfig = Get-BuildConfiguration `
112+ -ServerUrl "${{ github.server_url }}" `
113+ -GitRef "${{ github.ref }}" `
114+ -GitSha "${{ github.sha }}" `
115+ -GitHubOwner "${{ github.repository_owner }}" `
116+ -GitHubRepo "${{ github.repository }}" `
117+ -GithubToken "${{ github.token }}" `
118+ -NuGetApiKey "${{ secrets.NUGET_KEY }}" `
119+ -KtsuPackageKey "${{ secrets.KTSU_PACKAGE_KEY }}" `
120+ -WorkspacePath "${{ github.workspace }}" `
121+ -ExpectedOwner "ktsu-dev" `
122+ -ChangelogFile "CHANGELOG.md" `
123+ -AssetPatterns @("staging/*.nupkg", "staging/*.zip")
124+
125+ if (-not $buildConfig.Success) {
126+ throw $buildConfig.Error
127+ }
128+
129+ # Run the complete CI/CD pipeline
130+ $result = Invoke-CIPipeline `
131+ -BuildConfiguration $buildConfig.Data
132+
133+ if (-not $result.Success) {
134+ Write-Information "CI/CD pipeline failed: $($result.Error)" -Tags "Invoke-CIPipeline"
135+ Write-Information "Stack Trace: $($result.StackTrace)" -Tags "Invoke-CIPipeline"
136+ Write-Information "Build Configuration: $($buildConfig.Data | ConvertTo-Json -Depth 10)" -Tags "Invoke-CIPipeline"
137+ throw $result.Error
138+ }
139+
140+ # Set outputs for GitHub Actions from build configuration and pipeline result
141+ # Use pipeline result values when available (for skipped releases), otherwise use buildConfig
142+ if ($result.Data.SkippedRelease) {
143+ "version=$($result.Data.Version)" >> $env:GITHUB_OUTPUT
144+ "release_hash=$($result.Data.ReleaseHash)" >> $env:GITHUB_OUTPUT
145+ "should_release=$($buildConfig.Data.ShouldRelease)" >> $env:GITHUB_OUTPUT
146+ "skipped_release=true" >> $env:GITHUB_OUTPUT
147+ } else {
148+ "version=$($buildConfig.Data.Version)" >> $env:GITHUB_OUTPUT
149+ "release_hash=$($buildConfig.Data.ReleaseHash)" >> $env:GITHUB_OUTPUT
150+ "should_release=$($buildConfig.Data.ShouldRelease)" >> $env:GITHUB_OUTPUT
151+ # Check for skipped release from buildConfig as fallback
152+ if ($buildConfig.Data.SkippedRelease) {
153+ "skipped_release=true" >> $env:GITHUB_OUTPUT
154+ }
155+ }
156+
157+ - name : End SonarQube
158+ if : env.SONAR_TOKEN != '' && steps.pipeline.outputs.skipped_release != 'true'
159+ env :
160+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
161+ shell : powershell
162+ run : |
163+ .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
164+
165+ - name : Upload Coverage Report
166+ uses : actions/upload-artifact@v4
167+ if : always() && steps.pipeline.outputs.skipped_release != 'true'
168+ with :
169+ name : coverage-report
170+ path : |
171+ ./coverage/*
172+ retention-days : 7
173+
174+ winget :
175+ name : Update Winget Manifests
176+ needs : build
177+ if : needs.build.outputs.should_release == 'true' && needs.build.outputs.skipped_release != 'true'
178+ runs-on : windows-latest
179+ timeout-minutes : 10
180+ permissions :
181+ contents : write
182+
183+ steps :
184+ - name : Checkout Release Commit
185+ uses : actions/checkout@v4
186+ with :
187+ ref : ${{ needs.build.outputs.release_hash }}
188+ fetch-depth : 0 # Full history for better auto-detection
189+
190+ - name : Setup .NET SDK ${{ env.DOTNET_VERSION }}
191+ uses : actions/setup-dotnet@v4
192+ with :
193+ dotnet-version : ${{ env.DOTNET_VERSION }}.x
194+
195+ - name : Update Winget Manifests
196+ shell : pwsh
197+ env :
198+ GH_TOKEN : ${{ github.token }}
199+ run : |
200+ # Use enhanced script with auto-detection capabilities
201+ Write-Host "Updating winget manifests for version ${{ needs.build.outputs.version }}"
202+ .\scripts\update-winget-manifests.ps1 -Version "${{ needs.build.outputs.version }}"
203+
204+ - name : Upload Updated Manifests
205+ uses : actions/upload-artifact@v4
206+ with :
207+ name : winget-manifests-${{ needs.build.outputs.version }}
208+ path : winget/*.yaml
209+ retention-days : 30
103210
104211 security :
105212 name : Security Scanning
106213 needs : build
107- if : needs.build.outputs.should_release == 'true'
214+ if : needs.build.outputs.should_release == 'true' && needs.build.outputs.skipped_release != 'true'
108215 runs-on : windows-latest
109216 timeout-minutes : 10
110217 permissions :
111218 id-token : write # For dependency submission
112219 contents : write # For dependency submission
113220
114221 steps :
115- - name : Checkout Release Commit
116- uses : actions/checkout@v4
117- with :
118- ref : ${{ needs.build.outputs.release_hash }}
222+ - name : Checkout Release Commit
223+ uses : actions/checkout@v4
224+ with :
225+ ref : ${{ needs.build.outputs.release_hash }}
119226
120- - name : Detect Dependencies
121- uses : advanced-security/component-detection-dependency-submission-action@v0.0.2
227+ - name : Detect Dependencies
228+ uses : advanced-security/component-detection-dependency-submission-action@v0.0.2
0 commit comments