-
Notifications
You must be signed in to change notification settings - Fork 0
314 lines (266 loc) · 9.74 KB
/
Copy pathrelease.yml
File metadata and controls
314 lines (266 loc) · 9.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
name: Build, pack and release
on:
workflow_dispatch:
inputs:
debug_mode:
description: "Run the workflow in Debug Mode (skips NuGet and GitHub release)."
required: true
type: boolean
default: false
run_sonar:
description: "Analyze with Sonar and fail if quality gate fails. If set to false, also skips past testing."
required: true
type: boolean
default: true
push:
tags:
- 'v*.*.*'
permissions:
contents: read
jobs:
# Builds all the binaries.
# Also tests with MTP and forces the workflow to fail if SonarQube fails the quality gate.
# Only exception is if IGNORE_SONAR_ANALYSIS is disabled, where Sonar analysis will run,
# but won't force the quality gate to fail.
build-binaries:
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
arch: x64
rid-os: linux
- os: ubuntu-latest
arch: arm64
rid-os: linux
- os: ubuntu-latest
arch: arm
rid-os: linux
- os: windows-latest
arch: x64
rid-os: win
- os: windows-latest
arch: x86
rid-os: win
- os: windows-latest
arch: arm64
rid-os: win
- os: macos-latest
arch: x64
rid-os: osx
- os: macos-latest
arch: arm64
rid-os: osx
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Code
uses: actions/checkout@v7
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.x.x'
- name: Install Linux ARM compilation toolchain
if: matrix.rid-os == 'linux' && matrix.arch == 'arm'
run: |
sudo apt-get update
sudo apt-get install -y binutils-arm-linux-gnueabihf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
- name: Install Linux ARM64 compilation toolchain
if: matrix.rid-os == 'linux' && matrix.arch == 'arm64'
run: |
sudo apt-get update
sudo apt-get install -y binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
- name: Publish Native Project
shell: pwsh
run: |
$rid = "${{ matrix.rid-os }}-${{ matrix.arch }}"
$outputDir = "./dist/RSML.Native-$rid"
$dotnetArgs = @(
"./src/RSML.Native/RSML.Native.csproj",
"-c", "Release",
"-r", $rid,
"-o", $outputDir,
"--self-contained", "true"
)
if ("${{ matrix.rid-os }}" -eq "linux") {
if ("${{ matrix.arch }}" -eq "arm") {
$dotnetArgs += "-p:ObjCopyName=arm-linux-gnueabihf-objcopy"
$dotnetArgs += "-p:LinkerFlavor=lld"
}
elseif ("${{ matrix.arch }}" -eq "arm64") {
$dotnetArgs += "-p:ObjCopyName=aarch64-linux-gnu-objcopy"
$dotnetArgs += "-p:LinkerFlavor=lld"
}
}
dotnet publish @dotnetArgs
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Publish CLI Project
shell: pwsh
run: |
$rid = "${{ matrix.rid-os }}-${{ matrix.arch }}"
$outputDir = "./dist/RSML.CLI-$rid"
$dotnetArgs = @(
"./src/RSML.CLI/RSML.CLI.csproj",
"-c", "Release",
"-r", $rid,
"-o", $outputDir,
"--self-contained", "true"
)
if ("${{ matrix.rid-os }}" -eq "linux") {
if ("${{ matrix.arch }}" -eq "arm") {
$dotnetArgs += "-p:ObjCopyName=arm-linux-gnueabihf-objcopy"
$dotnetArgs += "-p:LinkerFlavor=lld"
}
elseif ("${{ matrix.arch }}" -eq "arm64") {
$dotnetArgs += "-p:ObjCopyName=aarch64-linux-gnu-objcopy"
$dotnetArgs += "-p:LinkerFlavor=lld"
}
}
dotnet publish @dotnetArgs
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Upload Native Artifacts
uses: actions/upload-artifact@v4
with:
name: rsml-native-${{ matrix.rid-os }}-${{ matrix.arch }}
path: ./dist/RSML.Native-${{ matrix.rid-os }}-${{ matrix.arch }}
if-no-files-found: error
- name: Upload CLI Artifacts
uses: actions/upload-artifact@v4
with:
name: rsml-cli-${{ matrix.rid-os }}-${{ matrix.arch }}
path: ./dist/RSML.CLI-${{ matrix.rid-os }}-${{ matrix.arch }}
if-no-files-found: error
# Release on NuGet and GitHub.
deploy:
permissions:
id-token: write
contents: write
needs: build-binaries
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.0.x'
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 24
- name: Download All Artifacts
uses: actions/download-artifact@v8
with:
path: ./all-binaries
- name: Restore solution
run: dotnet restore
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: 21
distribution: 'zulu'
- name: Restore
run: dotnet restore
- name: Cache SonarQube Cloud packages
uses: actions/cache@v5
if: github.ref_type == 'tag' || inputs.run_sonar == true
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@v5
if: github.ref_type == 'tag' || inputs.run_sonar == true
with:
path: ${{ runner.temp }}/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' && (github.ref_type == 'tag' || inputs.run_sonar == true)
run: |
mkdir -p ${{ runner.temp }}/scanner
dotnet tool update dotnet-sonarscanner --tool-path ${{ runner.temp }}/scanner
- name: Extract version from solution properties
if: github.ref_type != 'tag'
shell: pwsh
run: |
[xml]$xml = Get-Content Directory.Build.props
$prefix = $xml.SelectSingleNode("//VersionPrefix")?.InnerText
$suffix = $xml.SelectSingleNode("//VersionSuffix")?.InnerText
$semver = if ($suffix) { "$prefix-$suffix" } else { $prefix }
echo "SEMVER=$semver" >> $env:GITHUB_ENV
- name: Set version from tag
if: github.ref_type == 'tag'
shell: pwsh
run: echo "SEMVER=${{ github.ref_name }}" >> $env:GITHUB_ENV
- name: Begin analysis
if: github.ref_type == 'tag' || inputs.run_sonar == true
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
${{ runner.temp }}/scanner/dotnet-sonarscanner begin \
/k:"oas_RedSeaModernLanguage" \
/o:"oas" \
/v:"${{ env.SEMVER }}" \
/d:sonar.token="$SONAR_TOKEN" \
/d:sonar.cs.vscoveragexml.reportsPaths="**/TestResults/**/*.xml" \
/d:sonar.exclusions="**/*.png,**/*.jpg,**/*.jpeg,**/*.ico,**/*.gif" \
/d:sonar.qualitygate.wait=true \
/d:sonar.qualitygate.timeout=215
- name: Build solution (debug)
if: github.ref_type == 'tag' || inputs.run_sonar == true
run: dotnet build --configuration Debug --no-restore
- name: Test
if: github.ref_type == 'tag' || inputs.run_sonar == true
run: dotnet test --framework net10.0 --configuration Debug --no-build -- --coverage --coverage-output-format xml
- name: End analysis (fail if quality gate fails)
if: github.ref_type == 'tag' || inputs.run_sonar == true
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ${{ runner.temp }}/scanner/dotnet-sonarscanner end /d:sonar.token="$SONAR_TOKEN"
- name: Build solution (release)
run: dotnet build --configuration Release --no-restore
- name: Pack projects
run: dotnet pack --configuration Release --no-build --output ./nupkgs
# Get a short-lived NuGet API key (v1.2.0)
- name: Login to NuGet (OIDC → temp API key)
uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841
id: login
with:
user: ${{ secrets.NUGET_USER }}
- name: Push to NuGet
if: github.ref_type == 'tag' || inputs.debug_mode != true
run: |
dotnet nuget push "./nupkgs/*.nupkg" \
--api-key ${{ steps.login.outputs.NUGET_API_KEY }} \
--source "https://api.nuget.org/v3/index.json" \
--skip-duplicate
- name: Generate changelog
run: |
npx git-cliff@latest -o ${{ github.workspace }}-CHANGELOG.md --latest
cat ${{ github.workspace }}-CHANGELOG.md
- name: Prepare release assets
run: |
New-Item -ItemType Directory -Force -Path "./release-assets" | Out-Null
cd "./all-binaries"
Get-ChildItem -Directory | ForEach-Object {
$dir = $_.Name
$destPath = "../release-assets/$dir"
if ($dir -like "*-win-*") {
Write-Host "Windows: $destPath.zip"
Compress-Archive -Path "$dir/*" -DestinationPath "$destPath.zip" -Force
}
else {
Write-Host "Linux/macOS: $destPath.tar.gz"
tar -czf "$destPath.tar.gz" -C "$dir" .
}
}
- name: Create GitHub Release
if: github.ref_type == 'tag' || inputs.debug_mode != true
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # 3.0.2
with:
files: ./release-assets/*.tar.gz
body_path: ${{ github.workspace }}-CHANGELOG.txt
name: RSML ${{ github.ref_name }}