Skip to content
This repository was archived by the owner on Nov 14, 2025. It is now read-only.

.NET Workflow

.NET Workflow #307

Workflow file for this run

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 }}"