-
Notifications
You must be signed in to change notification settings - Fork 1
242 lines (203 loc) · 10.4 KB
/
Copy pathrelease.yml
File metadata and controls
242 lines (203 loc) · 10.4 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
name: Release
# Cut a release by pushing a tag: git tag -a v0.1.0 -m "..." && git push origin v0.1.0
#
# What ships is a single self-contained QuantumWake.exe: the server runs inside
# it and the dashboard is embedded in it, so there is no runtime to install, no
# folder to unpack and nothing to choose between. That is the whole deployment
# story for someone who does not want one.
#
# The CLI is published beside it for anyone verifying parser health, and is
# framework-dependent because that audience already has the SDK.
on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (e.g. v0.1.0)'
required: true
permissions:
contents: write
jobs:
release:
runs-on: windows-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.inputs.tag || github.ref }}
- uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.0.x'
- name: Version from tag
id: version
shell: pwsh
run: |
$tag = '${{ github.event.inputs.tag }}'
if (-not $tag) { $tag = '${{ github.ref_name }}' }
$version = $tag.TrimStart('v')
# The tag and the repository must agree, or the release lies about
# itself. Publishing passes -p:Version from the tag, so a forgotten
# bump would still produce a correctly stamped binary while the source
# - and the About page of anyone building locally - claimed the old
# number. Failing here is what makes "always bump the version" a rule
# rather than a habit.
$declared = ([xml](Get-Content Directory.Build.props)).SelectSingleNode('//Version').InnerText.Trim()
if ($declared -ne $version) {
throw "Tag $tag wants $version, but Directory.Build.props declares $declared. Bump the version, merge it, then tag the merge commit."
}
Write-Host "Releasing $version (tag and Directory.Build.props agree)"
"tag=$tag" | Out-File $env:GITHUB_OUTPUT -Append
"version=$version" | Out-File $env:GITHUB_OUTPUT -Append
# Never ship a build whose parser fixtures fail: the whole app is a log
# reader, so a red test here means the release would show empty views.
- name: Test
run: dotnet test Quantumwake.slnx -c Release
- name: Publish the application
shell: pwsh
run: |
$shortSha = "${{ github.sha }}".Substring(0, 7)
dotnet publish src/Quantumwake.Overlay -c Release -r win-x64 `
--self-contained true -p:PublishSingleFile=true `
-p:EnableCompressionInSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true `
-p:Version=${{ steps.version.outputs.version }} `
-p:InformationalVersion="${{ steps.version.outputs.version }}+$shortSha" -o dist/app
if ($LASTEXITCODE -ne 0) { throw 'publish failed' }
# A referenced executable project leaves its runtimeconfig behind. The
# app's own is inside the single file, so this one is just litter.
Remove-Item dist/app/Quantumwake.Server.runtimeconfig.json -ErrorAction SilentlyContinue
$files = Get-ChildItem dist/app -File
if ($files.Count -ne 1) { throw "expected one file, got: $($files.Name -join ', ')" }
- name: Publish the CLI
shell: pwsh
run: |
dotnet publish src/Quantumwake.Cli -c Release -r win-x64 --self-contained false `
-p:Version=${{ steps.version.outputs.version }} -o dist/cli
if ($LASTEXITCODE -ne 0) { throw 'cli publish failed' }
- name: Archive
id: archive
shell: pwsh
run: |
$version = '${{ steps.version.outputs.version }}'
# The executable ships on its own as well as in the zip: one click from
# the releases page, nothing to unpack.
Copy-Item dist/app/QuantumWake.exe "QuantumWake.exe"
$staging = 'dist/QuantumWake'
New-Item -ItemType Directory -Force $staging | Out-Null
Copy-Item dist/app/QuantumWake.exe $staging
Copy-Item dist/cli/* $staging -Recurse
Copy-Item README.md, LICENSE, NOTICE $staging
$zip = "QuantumWake-$version-win-x64.zip"
Compress-Archive -Path $staging -DestinationPath $zip
"asset=$zip" | Out-File $env:GITHUB_OUTPUT -Append
- name: Release
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
# What changed comes out of the README's release notes, so it is
# written once and cannot drift from what the repository claims. A
# version with no section still releases - the standing copy below is
# what most of a release page is - but it says so in the log, because
# a release that does not say what changed is worth noticing.
$version = '${{ steps.version.outputs.version }}'
$readme = Get-Content README.md -Raw
# Single-quoted and concatenated: in a double-quoted string PowerShell
# would read the regex's own $(...) groups as subexpressions to run.
$pattern = '(?ms)^### ' + [regex]::Escape($version) + '\s*$(.*?)(?=^### |\z)'
$section = [regex]::Match($readme, $pattern)
if ($section.Success) {
$summary = $section.Groups[1].Value.Trim()
$changed = "### What changed`n" + $summary + "`n`n"
Set-Content -Path release-summary.md -Value $summary -Encoding utf8
} else {
Write-Host "::warning::No '### $version' section in README.md; releasing without a changelog."
$summary = ''
$changed = ''
}
$notes = @"
**Quantum Wake ${{ steps.version.outputs.version }}** - a pilot's logbook for Star Citizen.
$changed
**Pre-1.0:** until version 1.0 this product will keep changing significantly
between releases - pages move, data formats shift, an update may re-read your
logs or ask you to re-enable an integration. Everything rebuilds from the
logs, so nothing is lost.
### Getting it running
Download **QuantumWake.exe** and double-click it. That is the whole
installation: nothing to unpack, no runtime to install, no settings to fill in.
Your Star Citizen install is found automatically.
Quantum Wake then sits in the notification area. Right-click it to open the
dashboard or quit. The in-game overlay is off by default - switch it on from
the dashboard's Settings page or the tray menu, and the choice is remembered.
``Ctrl+Alt+O`` toggles overlay click-through.
Windows will warn that the publisher is unknown - the executable is not code
signed, which costs money a free fan tool does not have. Choose **More info**,
then **Run anyway**.
The zip additionally contains the command-line tool, which prints per-event
match counts and parser health; it needs the .NET 10 runtime.
### What it does not do
Reads ``Game.log`` only. Nothing is written to the game directory, no memory is
touched, and nothing is injected. The app connects to the internet only where
you have said it may, from the Settings page - the optional datasets, and the
two that can go out unattended: the version check and the market-price
refresh, both off until you turn them on.
Star Citizen must run in Borderless Windowed for the overlay to be visible.
"@
gh release create '${{ steps.version.outputs.tag }}' `
'QuantumWake.exe' '${{ steps.archive.outputs.asset }}' `
--title 'Quantum Wake ${{ steps.version.outputs.version }}' `
--notes $notes
# Told to the support Discord after the release exists, not before: an
# announcement pointing at a release that failed to publish is worse than
# silence. Failing here must not fail the release either - the build is
# already out by this point, and a webhook is not a release step.
- name: Announce on Discord
if: success()
continue-on-error: true
shell: pwsh
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
run: |
if (-not $env:DISCORD_WEBHOOK) {
Write-Host "No DISCORD_WEBHOOK secret set; skipping the announcement."
exit 0
}
$version = '${{ steps.version.outputs.version }}'
$tag = '${{ steps.version.outputs.tag }}'
$url = "https://github.com/${{ github.repository }}/releases/tag/$tag"
# Discord refuses an embed description over 4096 characters, and a
# long release would take the whole announcement down with it. Cut on
# a line boundary so the last bullet is whole rather than clipped
# mid-word, and say that there is more rather than implying there is not.
# Written by the Release step from the README section it published,
# so the announcement and the release page cannot disagree.
$summary = if (Test-Path release-summary.md) {
(Get-Content release-summary.md -Raw).Trim()
} else {
"See the release page for what changed."
}
if ($summary.Length -gt 3500) {
$cut = $summary.Substring(0, 3500)
$lastBreak = $cut.LastIndexOf("`n")
if ($lastBreak -gt 0) { $cut = $cut.Substring(0, $lastBreak) }
$summary = $cut + "`n`n[Read the rest on the release page]($url)"
}
$payload = @{
username = "Quantum Wake"
embeds = @(@{
title = "Quantum Wake $version is out"
url = $url
description = $summary
color = 4771799
footer = @{ text = "Download QuantumWake.exe from the release page" }
})
} | ConvertTo-Json -Depth 6 -Compress
# The webhook is a secret and stays one: never echoed, never written
# to a file, and the response body is not printed either.
try {
Invoke-RestMethod -Uri $env:DISCORD_WEBHOOK -Method Post `
-ContentType 'application/json; charset=utf-8' `
-Body ([System.Text.Encoding]::UTF8.GetBytes($payload)) | Out-Null
Write-Host "Announced $version to Discord."
} catch {
Write-Host "::warning::Discord announcement failed: $($_.Exception.Message)"
}