Skip to content

Bump the ktsu group with 8 updates #522

Bump the ktsu group with 8 updates

Bump the ktsu group with 8 updates #522

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
workflow_dispatch: # Allow manual triggers
inputs:
version-bump:
description: 'Version bump type'
required: false
default: 'auto'
type: choice
options:
- auto
- patch
- minor
- major
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Default permissions
permissions:
contents: read
env:
DOTNET_VERSION: "10.0" # Only needed for actions/setup-dotnet
jobs:
build:
name: Build, Test & Release
runs-on: windows-latest
timeout-minutes: 20
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: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: 17
distribution: "zulu" # Alternative distribution options are available.
- name: Checkout Repository
uses: actions/checkout@v7
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@v6
with:
dotnet-version: ${{ env.DOTNET_VERSION }}.x
# setup-dotnet caches the NuGet global packages folder and keys it on a hash of these
# files. The csproj files alone are not enough: this repository uses central package
# management, so Directory.Packages.props is where versions actually live, and global.json
# pins the ktsu SDK versions, which are NuGet packages too. Without them a version bump in
# either file reuses the previous key, and because a cache hit never re-saves, the newly
# downloaded packages would never make it into the cache.
cache: true
cache-dependency-path: |
**/*.csproj
**/Directory.Packages.props
**/global.json
# Ensure NuGet packages directory exists for caching (prevents error when pipeline exits early)
- name: Ensure NuGet cache directory exists
run: New-Item -Path "$env:USERPROFILE\.nuget\packages" -ItemType Directory -Force
shell: pwsh
- name: Cache SonarQube Cloud packages
if: ${{ env.SONAR_TOKEN != '' }}
uses: actions/cache@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarQube Cloud scanner
if: ${{ env.SONAR_TOKEN != '' }}
id: cache-sonar-scanner
uses: actions/cache@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner
- name: Install SonarQube Cloud scanner
if: ${{ env.SONAR_TOKEN != '' && steps.cache-sonar-scanner.outputs.cache-hit != 'true' }}
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: pwsh
run: |
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
# KtsuBuild is cloned and compiled before the SonarQube window opens. The scanner injects its
# Roslyn analyzers into every project compiled between begin and end, so building KtsuBuild
# inside the window made it report KtsuBuild's own code smells against this repository. That is
# a compiler diagnostic rather than a reported issue, so sonar.exclusions cannot suppress it.
- name: Clone KtsuBuild (Latest Tag)
shell: pwsh
run: |
# Sorting by [version] rather than as text, so v1.8.15 wins over v1.8.9.
$tags = git ls-remote --tags https://github.com/ktsu-dev/KtsuBuild.git |
Select-String -Pattern 'refs/tags/(v\d+\.\d+\.\d+)$' |
ForEach-Object { $_.Matches[0].Groups[1].Value }
$latestTag = $tags | Sort-Object { [version]$_.Substring(1) } | Select-Object -Last 1
if ([string]::IsNullOrEmpty($latestTag)) {
Write-Host "No version tags found, falling back to HEAD"
git clone --depth 1 https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
}
else {
Write-Host "Cloning KtsuBuild at tag: $latestTag"
git clone --depth 1 --branch $latestTag https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
}
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Build KtsuBuild CLI
shell: pwsh
run: |
dotnet build "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Begin SonarQube
if: ${{ env.SONAR_TOKEN != '' }}
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: pwsh
run: |
# sonar.projectBaseDir is pinned to the workspace. Scanner for .NET v8 otherwise derives it
# from the projects it sees, and anything compiled outside the workspace widens it to a
# common ancestor, which pulls the runner's own checkouts under _actions and _temp into the
# file scan. Pinning it means only this repository is ever in scope, so no exclusions are
# needed for those directories.
.\.sonar\scanner\dotnet-sonarscanner begin /k:"${{ github.repository_owner }}_${{ github.event.repository.name }}" /o:"${{ github.repository_owner }}" /d:sonar.token="$env:SONAR_TOKEN" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.projectBaseDir="${{ github.workspace }}" /d:sonar.cs.vscoveragexml.reportsPaths="coverage/coverage.xml" /d:sonar.coverage.exclusions="**/*Test*.cs,**/*.Tests.cs,**/*.Tests/**/*,**/obj/**/*,**/*.dll,**/NativeExports.cs" /d:sonar.cs.vstest.reportsPaths="coverage/TestResults/**/*.trx" /d:sonar.exclusions="**/NativeExports.cs"
- name: Run KtsuBuild CI Pipeline
id: pipeline
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
NUGET_API_KEY: ${{ secrets.NUGET_KEY }}
KTSU_PACKAGE_KEY: ${{ secrets.KTSU_PACKAGE_KEY }}
EXPECTED_OWNER: ktsu-dev
run: |
# Run the CI pipeline
$versionBump = "${{ github.event.inputs.version-bump }}"
# Build arguments array - only add --version-bump if explicitly set (for backward compatibility during bootstrap)
$args = @("ci", "--workspace", "${{ github.workspace }}", "--verbose")
if (![string]::IsNullOrEmpty($versionBump) -and $versionBump -ne "auto") {
$args += @("--version-bump", $versionBump)
}
# --no-build because the CLI was compiled before the SonarQube window opened. Recompiling
# it here would pull the scanner's injected analyzers into KtsuBuild's own sources.
& dotnet run --no-build --project "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI" -- @args
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
# Set outputs for downstream jobs
$version = (Get-Content "${{ github.workspace }}/VERSION.md" -Raw).Trim()
"version=$version" >> $env:GITHUB_OUTPUT
$releaseHash = git rev-parse HEAD
"release_hash=$releaseHash" >> $env:GITHUB_OUTPUT
# Compute should_release (same logic as BuildConfigurationProvider)
$isMain = "${{ github.ref }}" -eq "refs/heads/main"
$isTagged = [bool](git tag --points-at "${{ github.sha }}" 2>$null)
$isFork = "${{ github.event.repository.fork }}" -eq "true"
$isExpectedOwner = "${{ github.repository_owner }}" -eq "ktsu-dev"
$isOfficial = (-not $isFork) -and $isExpectedOwner
$shouldRelease = $isMain -and (-not $isTagged) -and $isOfficial
"should_release=$($shouldRelease.ToString().ToLower())" >> $env:GITHUB_OUTPUT
- name: End SonarQube
if: env.SONAR_TOKEN != ''
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: pwsh
run: |
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="$env:SONAR_TOKEN"
- name: Upload Coverage Report
uses: actions/upload-artifact@v7
if: always()
with:
name: coverage-report
path: |
./coverage/*
retention-days: 7
if-no-files-found: ignore
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@v7
with:
ref: ${{ needs.build.outputs.release_hash }}
fetch-depth: 0 # Full history for better auto-detection
- name: Setup .NET SDK ${{ env.DOTNET_VERSION }}
uses: actions/setup-dotnet@v6
with:
dotnet-version: ${{ env.DOTNET_VERSION }}.x
- name: Clone KtsuBuild (Latest Tag)
shell: pwsh
run: |
# Sorting by [version] rather than as text, so v1.8.15 wins over v1.8.9.
$tags = git ls-remote --tags https://github.com/ktsu-dev/KtsuBuild.git |
Select-String -Pattern 'refs/tags/(v\d+\.\d+\.\d+)$' |
ForEach-Object { $_.Matches[0].Groups[1].Value }
$latestTag = $tags | Sort-Object { [version]$_.Substring(1) } | Select-Object -Last 1
if ([string]::IsNullOrEmpty($latestTag)) {
Write-Host "No version tags found, falling back to HEAD"
git clone --depth 1 https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
}
else {
Write-Host "Cloning KtsuBuild at tag: $latestTag"
git clone --depth 1 --branch $latestTag https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
}
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Update Winget Manifests
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
dotnet run --project "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI" -- winget generate --version "${{ needs.build.outputs.version }}" --workspace "${{ github.workspace }}" --verbose
- name: Upload Updated Manifests
uses: actions/upload-artifact@v7
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@v7
with:
ref: ${{ needs.build.outputs.release_hash }}
# Pinned to a full commit SHA rather than a tag. Tags are mutable, so a third party action
# referenced by tag can be repointed at different code after review. The trailing comment is
# the convention dependabot reads, so it still offers upgrades and rewrites both parts.
- name: Detect Dependencies
uses: advanced-security/component-detection-dependency-submission-action@31f25a8de68ae5ce2ca274bc28546a78683c15ce # v0.1.4