Repository navigation
183 lines (169 loc) · 7.61 KB
/
Copy pathrelease.yml
File metadata and controls
183 lines (169 loc) · 7.61 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
name: Release
# The release build lives in a workflow rather than on a laptop
# because SignPath only signs artifacts that a GitHub workflow produced.
# It verifies the origin of the build, so a binary assembled elsewhere
# and handed over with the API token is refused.
on:
push: { tags: ["v*"] }
workflow_dispatch:
inputs:
version:
description: "Version to release, e.g. 0.9.19"
required: true
permissions:
contents: write
jobs:
release:
name: Windows release
runs-on: windows-latest
env:
# whisper-rs-sys builds whisper.cpp from source, and the runners
# have AVX-512, which the default GGML_NATIVE=ON bakes in. Older
# CPUs then die during whisper decode.
CMAKE_ARGS: -DGGML_NATIVE=OFF
# The token is read through `env`, not through `secrets` in the
# step's `if`: the secrets context is not available there.
SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.91.0
- uses: Swatinem/rust-cache@v2
- name: Work out the version
id: version
shell: pwsh
run: |
$toml = Get-Content Cargo.toml -Raw
if ($toml -notmatch 'version\s*=\s*"([^"]+)"') { throw "no version in Cargo.toml" }
$fromToml = $Matches[1]
# A tag push carries the version; a manual run says it.
$wanted = if ("${{ github.event_name }}" -eq "workflow_dispatch") {
"${{ inputs.version }}"
} else {
"${{ github.ref_name }}" -replace '^v', ''
}
if ($wanted -ne $fromToml) {
throw "the tag says $wanted but Cargo.toml says $fromToml. Bump the version first."
}
"version=$wanted" >> $env:GITHUB_OUTPUT
- name: Build the release binary
run: cargo build --release -p caprust-app --no-default-features
- name: Install Inno Setup
# The installer is part of the release, so it has to be built
# inside the workflow for the signature to be trusted.
run: choco install innosetup --no-progress -y
- name: Build the installer and collect the release files
shell: pwsh
run: |
$v = "${{ steps.version.outputs.version }}"
New-Item -ItemType Directory -Force -Path installer\staging | Out-Null
New-Item -ItemType Directory -Force -Path release | Out-Null
Copy-Item target\release\caprust-app.exe installer\staging\caprust-app.exe -Force
# PowerShell needs the braces around a variable whose name has
# parentheses in it. Without them it reads $env:ProgramFiles and
# then treats (x86) as an expression, and the path never
# resolves.
$candidates = @(
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
"${env:ProgramFiles}\Inno Setup 6\ISCC.exe",
"${env:LOCALAPPDATA}\Programs\Inno Setup 6\ISCC.exe"
)
$iscc = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if (-not $iscc) {
# The package has moved before; look for it.
$iscc = Get-ChildItem -Path "${env:ProgramFiles(x86)}", "${env:ProgramFiles}" `
-Filter ISCC.exe -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1 -ExpandProperty FullName
}
if (-not $iscc) { throw "ISCC.exe not found after installing Inno Setup" }
Write-Host (" using " + $iscc)
& $iscc "/DMyAppVersion=$v" installer\caprust.iss
if ($LASTEXITCODE -ne 0) { throw "ISCC failed" }
Copy-Item "installer\dist\CapRust-$v-win64-setup.exe" release\ -Force
Copy-Item installer\staging\caprust-app.exe release\ -Force
Get-ChildItem release | ForEach-Object { Write-Host (" " + $_.Name + " " + $_.Length) }
- name: Upload the unsigned release files
id: upload
uses: actions/upload-artifact@v4
with:
name: caprust-release-unsigned
path: release
if-no-files-found: error
retention-days: 7
- name: Request the signature
# Only once SignPath has approved the project and the secrets
# exist. Before that the release is published unsigned, which is
# where the beta has been anyway.
id: sign
if: ${{ env.SIGNPATH_API_TOKEN != '' }}
uses: signpath/github-action-submit-signing-request@v3
with:
api-token: '${{ env.SIGNPATH_API_TOKEN }}'
organization-id: '${{ secrets.SIGNPATH_ORGANIZATION_ID }}'
project-slug: '${{ secrets.SIGNPATH_PROJECT_SLUG }}'
signing-policy-slug: '${{ secrets.SIGNPATH_SIGNING_POLICY_SLUG }}'
artifact-configuration-slug: '${{ vars.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}'
github-artifact-id: '${{ steps.upload.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: signed
parameters: |
version: "${{ steps.version.outputs.version }}"
- name: Collect the signed files
if: ${{ steps.sign.outputs.signing-request-id != '' }}
shell: pwsh
run: |
$v = "${{ steps.version.outputs.version }}"
Copy-Item signed\CapRust-$v-win64-setup.exe release\ -Force
Copy-Item signed\caprust-app.exe release\ -Force
- name: Verify the signature
if: ${{ steps.sign.outputs.signing-request-id != '' }}
shell: pwsh
run: |
# A signed file that does not verify is worse than an unsigned
# one, because it looks done.
Add-Type -AssemblyName System.IO.Compression.FileSystem
$v = "${{ steps.version.outputs.version }}"
$setup = "release\CapRust-$v-win64-setup.exe"
$sig = Get-AuthenticodeSignature $setup
Write-Host (" setup.exe status: " + $sig.Status)
if ($sig.Status -ne 'Valid') {
throw "the setup.exe signature is $($sig.Status), not Valid"
}
$portable = "release\caprust-app.exe"
$sig2 = Get-AuthenticodeSignature $portable
Write-Host (" caprust-app.exe status: " + $sig2.Status)
if ($sig2.Status -ne 'Valid') {
throw "the portable binary's signature is $($sig2.Status), not Valid"
}
- name: Pack the portable zip
shell: pwsh
run: |
$v = "${{ steps.version.outputs.version }}"
Compress-Archive -Path release\caprust-app.exe -DestinationPath "release\caprust-$v-windows.zip" -CompressionLevel Optimal
Remove-Item release\caprust-app.exe
- name: Publish the release
shell: pwsh
env:
GH_TOKEN: '${{ github.token }}'
run: |
$v = "${{ steps.version.outputs.version }}"
$files = @(Get-ChildItem release -File | ForEach-Object { $_.FullName })
if ($files.Count -eq 0) { throw "nothing to publish" }
gh release create "v$v" @files `
--title "v$v" `
--generate-notes
Write-Host "published v$v"
- name: Upload the signed files to an existing release
# For a re-run of a tag that already has a release, the create
# above fails and the files are attached instead.
if: failure()
shell: pwsh
env:
GH_TOKEN: '${{ github.token }}'
run: |
$v = "${{ steps.version.outputs.version }}"
$files = @(Get-ChildItem release -File -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName })
if ($files.Count -eq 0) {
Write-Host "nothing to upload"
exit 0
}
gh release upload "v$v" @files --clobber