This repository was archived by the owner on Nov 14, 2025. It is now read-only.
.NET Workflow #307
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: .NET Workflow | |
| on: | |
| push: | |
| branches: [main, develop] | |
| paths-ignore: | |
| ["**.md", ".github/ISSUE_TEMPLATE/**", ".github/pull_request_template.md"] | |
| pull_request: | |
| paths-ignore: | |
| ["**.md", ".github/ISSUE_TEMPLATE/**", ".github/pull_request_template.md"] | |
| schedule: | |
| - cron: "0 23 * * *" # Daily at 11 PM UTC | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Default permissions | |
| permissions: read-all | |
| env: | |
| DOTNET_VERSION: "9.0" # Only needed for actions/setup-dotnet | |
| jobs: | |
| build: | |
| name: Build, Test & Release | |
| runs-on: windows-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: write # For creating releases and committing metadata | |
| packages: write # For publishing packages | |
| outputs: | |
| version: ${{ steps.pipeline.outputs.version }} | |
| release_hash: ${{ steps.pipeline.outputs.release_hash }} | |
| should_release: ${{ steps.pipeline.outputs.should_release }} | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Full history for versioning | |
| fetch-tags: true | |
| lfs: true | |
| submodules: recursive | |
| persist-credentials: true | |
| - name: Setup .NET SDK ${{ env.DOTNET_VERSION }} | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }}.x | |
| cache: true | |
| cache-dependency-path: "**/*.csproj" | |
| - name: Run PSBuild Pipeline | |
| id: pipeline | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # Import the PSBuild module | |
| Import-Module ${{ github.workspace }}/scripts/PSBuild.psm1 | |
| # Get build configuration | |
| $buildConfig = Get-BuildConfiguration ` | |
| -ServerUrl "${{ github.server_url }}" ` | |
| -GitRef "${{ github.ref }}" ` | |
| -GitSha "${{ github.sha }}" ` | |
| -GitHubOwner "${{ github.repository_owner }}" ` | |
| -GitHubRepo "${{ github.repository }}" ` | |
| -GithubToken "${{ github.token }}" ` | |
| -NuGetApiKey "${{ secrets.NUGET_KEY }}" ` | |
| -WorkspacePath "${{ github.workspace }}" ` | |
| -ExpectedOwner "ktsu-dev" ` | |
| -ChangelogFile "CHANGELOG.md" ` | |
| -AssetPatterns @("staging/*.nupkg", "staging/*.zip") | |
| if (-not $buildConfig.Success) { | |
| throw $buildConfig.Error | |
| } | |
| # Run the complete CI/CD pipeline | |
| $result = Invoke-CIPipeline ` | |
| -BuildConfiguration $buildConfig.Data | |
| if (-not $result.Success) { | |
| Write-Information "CI/CD pipeline failed: $($result.Error)" -Tags "Invoke-CIPipeline" | |
| Write-Information "Stack Trace: $($result.StackTrace)" -Tags "Invoke-CIPipeline" | |
| Write-Information "Build Configuration: $($buildConfig.Data | ConvertTo-Json -Depth 10)" -Tags "Invoke-CIPipeline" | |
| throw $result.Error | |
| } | |
| # Set outputs for GitHub Actions from build configuration | |
| "version=$($buildConfig.Data.Version)" >> $env:GITHUB_OUTPUT | |
| "release_hash=$($buildConfig.Data.ReleaseHash)" >> $env:GITHUB_OUTPUT | |
| "should_release=$($buildConfig.Data.ShouldRelease)" >> $env:GITHUB_OUTPUT | |
| - name: Upload Coverage Report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: coverage-report | |
| path: ./coverage | |
| retention-days: 7 | |
| winget: | |
| name: Update Winget Manifests | |
| needs: build | |
| if: needs.build.outputs.should_release == 'true' | |
| runs-on: windows-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout Release Commit | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.build.outputs.release_hash }} | |
| fetch-depth: 0 | |
| - name: Update Winget Manifests | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| .\scripts\update-winget-manifests.ps1 -Version "${{ needs.build.outputs.version }}" | |
| - name: Upload Updated Manifests | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: winget-manifests-${{ needs.build.outputs.version }} | |
| path: winget/*.yaml | |
| retention-days: 30 | |
| security: | |
| name: Security Scanning | |
| needs: build | |
| if: needs.build.outputs.should_release == 'true' | |
| runs-on: windows-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| id-token: write # For dependency submission | |
| contents: write # For dependency submission | |
| steps: | |
| - name: Checkout Release Commit | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.build.outputs.release_hash }} | |
| - name: Detect Dependencies | |
| uses: advanced-security/component-detection-dependency-submission-action@v0.0.2 | |
| SonarQube: | |
| name: SonarQube | |
| needs: build | |
| runs-on: windows-latest | |
| steps: | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: 17 | |
| distribution: "zulu" # Alternative distribution options are available. | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| lfs: true | |
| submodules: recursive | |
| persist-credentials: true | |
| token: ${{ github.token }} | |
| - name: Determine Target Commit for Analysis | |
| shell: pwsh | |
| run: | | |
| # Check the context to determine the appropriate commit to analyze | |
| $eventName = "${{ github.event_name }}" | |
| $releaseHash = "${{ needs.build.outputs.release_hash }}" | |
| $shouldRelease = "${{ needs.build.outputs.should_release }}" | |
| Write-Host "Event: $eventName" | |
| Write-Host "Should Release: $shouldRelease" | |
| Write-Host "Release Hash: $releaseHash" | |
| Write-Host "Current commit: $(git rev-parse HEAD)" | |
| if ($eventName -eq "pull_request") { | |
| # For PRs, analyze the merge commit (current HEAD) | |
| # PSBuild can't commit/push in PR context, so release_hash won't be valid | |
| Write-Host "Pull Request build detected. Using PR merge commit for analysis." | |
| Write-Host "Analyzing commit: $(git rev-parse HEAD)" | |
| } elseif ($shouldRelease -eq 'true' -and -not [string]::IsNullOrWhiteSpace($releaseHash)) { | |
| # For release builds on main branch, try to use the release commit | |
| Write-Host "Release build detected. Attempting to checkout release commit: $releaseHash" | |
| # Fetch latest to ensure we have the release commit | |
| git fetch origin | |
| git fetch --tags | |
| # Verify the commit exists before checking out | |
| $commitExists = git cat-file -e "$releaseHash" 2>$null | |
| if ($LASTEXITCODE -eq 0) { | |
| git checkout "$releaseHash" | |
| Write-Host "Successfully checked out release commit: $releaseHash" | |
| } else { | |
| Write-Host "Release commit $releaseHash not found, staying on current commit" | |
| Write-Host "This might indicate the commit/push failed in the build process" | |
| Write-Host "Analyzing current commit: $(git rev-parse HEAD)" | |
| } | |
| } else { | |
| # For non-release builds (develop branch, etc.) | |
| Write-Host "Non-release build detected. Using current commit for analysis." | |
| Write-Host "Analyzing commit: $(git rev-parse HEAD)" | |
| } | |
| - name: Cache SonarQube Cloud packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~\sonar\cache | |
| key: ${{ runner.os }}-sonar | |
| restore-keys: ${{ runner.os }}-sonar | |
| - name: Cache SonarQube Cloud scanner | |
| id: cache-sonar-scanner | |
| uses: actions/cache@v4 | |
| with: | |
| path: .\.sonar\scanner | |
| key: ${{ runner.os }}-sonar-scanner | |
| restore-keys: ${{ runner.os }}-sonar-scanner | |
| - name: Install SonarQube Cloud scanner | |
| if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' | |
| shell: powershell | |
| run: | | |
| New-Item -Path .\.sonar\scanner -ItemType Directory | |
| dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner | |
| - name: Build and analyze | |
| env: | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| shell: powershell | |
| run: | | |
| .\.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" | |
| dotnet build | |
| .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" |