Skip to content

Commit dd93cbe

Browse files
SyncFileContentsSyncFileContents
authored andcommitted
Sync .github\workflows\dotnet.yml
1 parent fedf3fa commit dd93cbe

1 file changed

Lines changed: 79 additions & 47 deletions

File tree

.github/workflows/dotnet.yml

Lines changed: 79 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ jobs:
5050

5151
steps:
5252
- name: Set up JDK 17
53-
uses: actions/setup-java@v4
53+
uses: actions/setup-java@v5
5454
with:
5555
java-version: 17
5656
distribution: "zulu" # Alternative distribution options are available.
5757

5858
- name: Checkout Repository
59-
uses: actions/checkout@v4
59+
uses: actions/checkout@v7
6060
with:
6161
fetch-depth: 0 # Full history for versioning
6262
fetch-tags: true
@@ -65,11 +65,20 @@ jobs:
6565
persist-credentials: true
6666

6767
- name: Setup .NET SDK ${{ env.DOTNET_VERSION }}
68-
uses: actions/setup-dotnet@v4
68+
uses: actions/setup-dotnet@v6
6969
with:
7070
dotnet-version: ${{ env.DOTNET_VERSION }}.x
71+
# setup-dotnet caches the NuGet global packages folder and keys it on a hash of these
72+
# files. The csproj files alone are not enough: this repository uses central package
73+
# management, so Directory.Packages.props is where versions actually live, and global.json
74+
# pins the ktsu SDK versions, which are NuGet packages too. Without them a version bump in
75+
# either file reuses the previous key, and because a cache hit never re-saves, the newly
76+
# downloaded packages would never make it into the cache.
7177
cache: true
72-
cache-dependency-path: "**/*.csproj"
78+
cache-dependency-path: |
79+
**/*.csproj
80+
**/Directory.Packages.props
81+
**/global.json
7382
7483
# Ensure NuGet packages directory exists for caching (prevents error when pipeline exits early)
7584
- name: Ensure NuGet cache directory exists
@@ -78,7 +87,7 @@ jobs:
7887

7988
- name: Cache SonarQube Cloud packages
8089
if: ${{ env.SONAR_TOKEN != '' }}
81-
uses: actions/cache@v4
90+
uses: actions/cache@v6
8291
env:
8392
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
8493
with:
@@ -89,7 +98,7 @@ jobs:
8998
- name: Cache SonarQube Cloud scanner
9099
if: ${{ env.SONAR_TOKEN != '' }}
91100
id: cache-sonar-scanner
92-
uses: actions/cache@v4
101+
uses: actions/cache@v6
93102
env:
94103
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
95104
with:
@@ -101,41 +110,52 @@ jobs:
101110
if: ${{ env.SONAR_TOKEN != '' && steps.cache-sonar-scanner.outputs.cache-hit != 'true' }}
102111
env:
103112
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
104-
shell: powershell
113+
shell: pwsh
105114
run: |
106115
New-Item -Path .\.sonar\scanner -ItemType Directory
107116
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
108117
109-
- name: Configure SonarQube exclusions
110-
shell: bash
118+
# KtsuBuild is cloned and compiled before the SonarQube window opens. The scanner injects its
119+
# Roslyn analyzers into every project compiled between begin and end, so building KtsuBuild
120+
# inside the window made it report KtsuBuild's own code smells against this repository. That is
121+
# a compiler diagnostic rather than a reported issue, so sonar.exclusions cannot suppress it.
122+
- name: Clone KtsuBuild (Latest Tag)
123+
shell: pwsh
111124
run: |
112-
EXCLUSIONS="_temp/**,_actions/**"
113-
if [ "${{ github.event.repository.name }}" != "KtsuBuild" ]; then
114-
EXCLUSIONS="$EXCLUSIONS,**/KtsuBuild/**"
115-
fi
116-
# NativeExports.cs is intentionally unsafe C ABI boundary code; exclude from all analysis.
117-
EXCLUSIONS="$EXCLUSIONS,**/NativeExports.cs"
118-
echo "SONAR_EXCLUSIONS=$EXCLUSIONS" >> $GITHUB_ENV
125+
# Sorting by [version] rather than as text, so v1.8.15 wins over v1.8.9.
126+
$tags = git ls-remote --tags https://github.com/ktsu-dev/KtsuBuild.git |
127+
Select-String -Pattern 'refs/tags/(v\d+\.\d+\.\d+)$' |
128+
ForEach-Object { $_.Matches[0].Groups[1].Value }
129+
$latestTag = $tags | Sort-Object { [version]$_.Substring(1) } | Select-Object -Last 1
130+
131+
if ([string]::IsNullOrEmpty($latestTag)) {
132+
Write-Host "No version tags found, falling back to HEAD"
133+
git clone --depth 1 https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
134+
}
135+
else {
136+
Write-Host "Cloning KtsuBuild at tag: $latestTag"
137+
git clone --depth 1 --branch $latestTag https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
138+
}
139+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
140+
141+
- name: Build KtsuBuild CLI
142+
shell: pwsh
143+
run: |
144+
dotnet build "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI"
145+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
119146
120147
- name: Begin SonarQube
121148
if: ${{ env.SONAR_TOKEN != '' }}
122149
env:
123150
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
124-
shell: powershell
125-
run: |
126-
.\.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.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="${{ env.SONAR_EXCLUSIONS }}"
127-
128-
- name: Clone KtsuBuild (Latest Tag)
151+
shell: pwsh
129152
run: |
130-
LATEST_TAG=$(git ls-remote --tags https://github.com/ktsu-dev/KtsuBuild.git | grep -o 'refs/tags/v[0-9]*\.[0-9]*\.[0-9]*$' | sed 's/refs\/tags\///' | sort -V | tail -1 || true)
131-
if [ -z "$LATEST_TAG" ]; then
132-
echo "No version tags found, falling back to HEAD"
133-
git clone --depth 1 https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
134-
else
135-
echo "Cloning KtsuBuild at tag: $LATEST_TAG"
136-
git clone --depth 1 --branch "$LATEST_TAG" https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
137-
fi
138-
shell: bash
153+
# sonar.projectBaseDir is pinned to the workspace. Scanner for .NET v8 otherwise derives it
154+
# from the projects it sees, and anything compiled outside the workspace widens it to a
155+
# common ancestor, which pulls the runner's own checkouts under _actions and _temp into the
156+
# file scan. Pinning it means only this repository is ever in scope, so no exclusions are
157+
# needed for those directories.
158+
.\.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"
139159
140160
- name: Run KtsuBuild CI Pipeline
141161
id: pipeline
@@ -155,7 +175,9 @@ jobs:
155175
$args += @("--version-bump", $versionBump)
156176
}
157177
158-
& dotnet run --project "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI" -- @args
178+
# --no-build because the CLI was compiled before the SonarQube window opened. Recompiling
179+
# it here would pull the scanner's injected analyzers into KtsuBuild's own sources.
180+
& dotnet run --no-build --project "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI" -- @args
159181
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
160182
161183
# Set outputs for downstream jobs
@@ -178,12 +200,12 @@ jobs:
178200
if: env.SONAR_TOKEN != ''
179201
env:
180202
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
181-
shell: powershell
203+
shell: pwsh
182204
run: |
183-
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
205+
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="$env:SONAR_TOKEN"
184206
185207
- name: Upload Coverage Report
186-
uses: actions/upload-artifact@v4
208+
uses: actions/upload-artifact@v7
187209
if: always()
188210
with:
189211
name: coverage-report
@@ -203,27 +225,34 @@ jobs:
203225

204226
steps:
205227
- name: Checkout Release Commit
206-
uses: actions/checkout@v4
228+
uses: actions/checkout@v7
207229
with:
208230
ref: ${{ needs.build.outputs.release_hash }}
209231
fetch-depth: 0 # Full history for better auto-detection
210232

211233
- name: Setup .NET SDK ${{ env.DOTNET_VERSION }}
212-
uses: actions/setup-dotnet@v4
234+
uses: actions/setup-dotnet@v6
213235
with:
214236
dotnet-version: ${{ env.DOTNET_VERSION }}.x
215237

216238
- name: Clone KtsuBuild (Latest Tag)
239+
shell: pwsh
217240
run: |
218-
LATEST_TAG=$(git ls-remote --tags https://github.com/ktsu-dev/KtsuBuild.git | grep -o 'refs/tags/v[0-9]*\.[0-9]*\.[0-9]*$' | sed 's/refs\/tags\///' | sort -V | tail -1 || true)
219-
if [ -z "$LATEST_TAG" ]; then
220-
echo "No version tags found, falling back to HEAD"
241+
# Sorting by [version] rather than as text, so v1.8.15 wins over v1.8.9.
242+
$tags = git ls-remote --tags https://github.com/ktsu-dev/KtsuBuild.git |
243+
Select-String -Pattern 'refs/tags/(v\d+\.\d+\.\d+)$' |
244+
ForEach-Object { $_.Matches[0].Groups[1].Value }
245+
$latestTag = $tags | Sort-Object { [version]$_.Substring(1) } | Select-Object -Last 1
246+
247+
if ([string]::IsNullOrEmpty($latestTag)) {
248+
Write-Host "No version tags found, falling back to HEAD"
221249
git clone --depth 1 https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
222-
else
223-
echo "Cloning KtsuBuild at tag: $LATEST_TAG"
224-
git clone --depth 1 --branch "$LATEST_TAG" https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
225-
fi
226-
shell: bash
250+
}
251+
else {
252+
Write-Host "Cloning KtsuBuild at tag: $latestTag"
253+
git clone --depth 1 --branch $latestTag https://github.com/ktsu-dev/KtsuBuild.git "${{ runner.temp }}/KtsuBuild"
254+
}
255+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
227256
228257
- name: Update Winget Manifests
229258
shell: pwsh
@@ -233,7 +262,7 @@ jobs:
233262
dotnet run --project "${{ runner.temp }}/KtsuBuild/KtsuBuild.CLI" -- winget generate --version "${{ needs.build.outputs.version }}" --workspace "${{ github.workspace }}" --verbose
234263
235264
- name: Upload Updated Manifests
236-
uses: actions/upload-artifact@v4
265+
uses: actions/upload-artifact@v7
237266
with:
238267
name: winget-manifests-${{ needs.build.outputs.version }}
239268
path: winget/*.yaml
@@ -251,9 +280,12 @@ jobs:
251280

252281
steps:
253282
- name: Checkout Release Commit
254-
uses: actions/checkout@v4
283+
uses: actions/checkout@v7
255284
with:
256285
ref: ${{ needs.build.outputs.release_hash }}
257286

287+
# Pinned to a full commit SHA rather than a tag. Tags are mutable, so a third party action
288+
# referenced by tag can be repointed at different code after review. The trailing comment is
289+
# the convention dependabot reads, so it still offers upgrades and rewrites both parts.
258290
- name: Detect Dependencies
259-
uses: advanced-security/component-detection-dependency-submission-action@v0.0.2
291+
uses: advanced-security/component-detection-dependency-submission-action@31f25a8de68ae5ce2ca274bc28546a78683c15ce # v0.1.4

0 commit comments

Comments
 (0)