-
Notifications
You must be signed in to change notification settings - Fork 135
382 lines (362 loc) · 18.2 KB
/
windows.yml
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
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
#-----------------------------------------------------------------------------------------------------------------------
# .github/workflows/windows.yml is part of Brewtarget, and is copyright the following authors 2021-2024:
# • Artem Martynov <[email protected]>
# • Chris Speck <[email protected]>
# • Mattias Måhl <[email protected]>
# • Matt Young <[email protected]>
#
# Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#-----------------------------------------------------------------------------------------------------------------------
name: Windows
#
# These are all the events that trigger this workflow run. Most are self-explanatory. We need workflow_dispatch to be
# able to run the workflow manually.
#
on:
push:
branches:
- develop
- "stable/**"
pull_request:
branches:
- develop
schedule:
- cron: "0 2 * * *"
workflow_dispatch:
#
# Normally, on the scheduled builds, we only do the "test" signing with SignPath because doing the "release" signing
# requires a manual approval step in our SignPath account. When we want to do a proper "release" signing, then we
# trigger a manual build and set this variable to true (via the GitHub UI prompt at the time the build is
# initiated).
#
inputs:
signingType:
#
# Note that, per GitHub doco, "If you attempt to dereference a nonexistent property, it will evaluate to an
# empty string." Hence it's easier later on in the code if we use a choice here than a boolean.
#
description: 'Do a "release" signing (rather than just a "test" one)'
required: true
type: choice
options:
- test
- release
default: 'test'
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build-win:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include: [
# In the past, we built only 32-bit packages (i686 architecture) on Windows because of problems getting 64-bit
# versions of NSIS plugins to work. However, we now invoke NSIS without plugins, so the 64-bit build seems to
# be working.
#
# As of January 2024, some of the 32-bit MSYS2 packages/groups we were previously relying on previously are no
# longer available. So now, we only build 64-bit packages (x86_64 architecture) on Windows.
{ msystem: MINGW64, arch: x86_64 },
]
steps:
- uses: actions/checkout@v4
with:
path: temp
fetch-depth: 0
submodules: recursive
#
# Install MSYS2, then Python, then Pip
#
# We need Python 3.10 or later to run the bt script
#
# I tried using the separate actions/setup-python@v4 action, but it doesn't seem to result in the Python
# executable being visible in the MSYS2 environment. So, instead, we install from inside MSYS2. (According to
# https://packages.msys2.org/package/mingw-w64-x86_64-python, this is Python 3.10.9 as of 2022-12-10.)
#
# (In theory, an alternative approach would be to install Python, then run 'python -m ensurepip --upgrade' which,
# per https://docs.python.org/3/library/ensurepip.html, is the official Python way to bootstrap Pip. However,
# this did not seem to work properly in MSYS2 when I tried it.)
#
# Note that you _don't_ want to install the 'python' package here as it has some subtle differences from
# installing 'mingw-w64-i686-python'. (Same applies for 'python-pip' vs 'mingw-w64-i686-python-pip'.) Some of
# these differences are about where things are installed, but some are about how Python behaves, eg what
# platform.system() returns. See comments at https://github.com/conan-io/conan/issues/2638 for more.)
#
# We install the tree command here as, although it's not needed to do the build itself, it's useful for diagnosing
# certain build problems (eg to see what changes certain parts of the build have made to the build directory
# tree) when the build is running as a GitHub action. (If need be, you can also download the entire build
# directory within a day of a failed build running, but you need a decent internet connection for this as it's
# quite large.)
#
- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
install: >-
mingw-w64-${{ matrix.arch }}-python
mingw-w64-${{ matrix.arch }}-python-pip
tree
update: true
release: true
path-type: strict
- name: Move Checkout
run: |
Copy-Item -Path "./temp" -Destination "C:/_" -Recurse
#
# On Windows, there are a couple of extra things we need to do before running the bt script:
#
# - For historical reasons, Linux and other platforms need to run both Python v2 (still used by some bits of
# system) and Python v3 (eg that you installed yourself) so there are usually two corresponding Python
# executables, python2 and python3. On Windows there is only whatever Python you installed and it's called
# python.exe. To keep the shebang in the bt script working, we just make a softlink to python called python3.
#
# - Getting Unicode input/output to work is fun. We should already have a Unicode locale, but it seems we also
# need to set PYTHONIOENCODING (see https://docs.python.org/3/using/cmdline.html#envvar-PYTHONIOENCODING, even
# though it seems to imply you don't need to set it on recent versions of Python).
#
# - The version of Pip we install above does not put it in the "right" place. Specifically it will not be in the
# PATH when we run bt. The following seems to be the least hacky way around this:
# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
# python get-pip.py
# python -m pip install -U --force-reinstall pip
# See https://stackoverflow.com/questions/48087004/installing-pip-on-msys for more discussion on this.
#
- name: Install Frameworks and Libraries, and set up Meson build environment
shell: msys2 {0}
run: |
cd /C/_/
echo "Working directory is:"
pwd
echo "Installed Python is:"
which python
python --version
echo "Installed pip is:"
which pip
pip --version
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
python -m pip install -U --force-reinstall pip
pip --version
echo "Locale:"
locale
export PYTHONIOENCODING=utf8
echo "Ensuring that python3 symlink / executable exists"
if [[ ! -f $(dirname $(which python))/python3 ]]; then ln -s $(which python) $(dirname $(which python))/python3; fi
echo "Running ./bt -v setup all"
./bt -v setup all
# In theory we don't need the next bit, as the bt script does it. In practice, for reasons I haven't yet bottomed
# out, the CMake/CPack invocation of NSIS complains it can't find Locate.nsh - but only on the Brewtarget build,
# not the Brewken one, even though all the build scripts etc are almost identical.
#
# Note that this is PowerShell, so absolute paths on the C drive begin C:/ rather than /C/ in MSYS2
- name: Download NSIS plugins
run: |
New-Item -ItemType Directory -Force -Path C:/_/build/nsis
Invoke-WebRequest -Uri https://nsis.sourceforge.io/mediawiki/images/a/af/Locate.zip -OutFile C:/_/build/nsis/Locate.zip
Expand-Archive -Path C:/_/build/nsis/Locate.zip -DestinationPath C:/_/build/nsis/Locate
Invoke-WebRequest -Uri https://nsis.sourceforge.io/mediawiki/images/7/76/Nsislog.zip -OutFile C:/_/build/nsis/Nsislog.zip
Expand-Archive -Path C:/_/build/nsis/Nsislog.zip -DestinationPath C:/_/build/nsis/Nsislog
Tree /f C:/_/build
# The configure script does default set-up for CMake that is enough for us here
- name: CMake Config
shell: msys2 {0}
run: |
cd /C/_
./configure
- name: Build (with Meson)
shell: msys2 {0}
run: |
cd /C/_/mbuild
pwd
meson compile
# The pwd and find ../third-party commands below are just diagnostics, but it's generally useful to have too
# much rather than not enough diagnostic info on these GitHub action builds
#
# This is the same reason we specify the --verbose option on CMake
- name: Build (with CMake)
shell: msys2 {0}
run: |
cd /C/_/build
pwd
tree -sh
cmake --build . --verbose
ls
# The 'export QT_DEBUG_PLUGINS=1' give us diagnostics in the event that there are problems initialising QT
# The 'export QT_QPA_PLATFORM=offscreen' stops Qt's xcb sub-module trying to connect to a non-existent display
# (which would cause the test runner to abort before running any tests).
- name: Test (via Meson)
shell: msys2 {0}
run: |
cd /C/_/mbuild
export QT_DEBUG_PLUGINS=1
export QT_QPA_PLATFORM=offscreen
meson test
- name: Test (via CMake)
shell: msys2 {0}
run: |
cd /C/_/build
cmake --build . --target test
#
# See above for explanation of the extra things we need to do on Windows before running the bt script. Most of
# that does not need doing again here, but PYTHONIOENCODING does need setting again.
#
# Note that, although we continue to support CMake for local builds and installs, we no longer support packaging
# with CPack/CMake. The bt build script packaging gives us better control over the packaging process.
#
- name: Package
shell: msys2 {0}
run: |
cd /C/_/
echo "Working directory is:"
pwd
echo "Installed Python is:"
which python
python --version
echo "Installed pip is:"
which pip
pip --version
export PYTHONIOENCODING=utf8
echo "Running ./bt -v package"
./bt -v package
cd mbuild/packages
mkdir windows/signed
pwd
tree -sh
#
# For now, we'll still upload the unsigned binaries before we try to sign them, so that we at least have a
# fallback if there is some problem with the signing process
#
# Note that the ID of this step is referenced in the signing step (so it can grab the unsigned binaries to sign
# them).
#
- name: Upload unsigned Windows binaries (installers)
id: upload-unsigned-artifact
if: ${{ success()}}
uses: actions/upload-artifact@v4
with:
name: brewtarget-dev-${{ matrix.msystem }}
path: |
C:/_/mbuild/packages/windows/Brewtarget*Installer.exe
C:/_/mbuild/packages/windows/Brewtarget*Installer.exe.sha256sum
retention-days: 7
#
# Sign the Windows binaries using our Signpath certificate. Note that this involves sending the binary to the
# remote SignPath service where the signing actually happens. We need to have an account and credentials with
# that service to use it, so this step can't be done in forked repositories.
#
# Various settings here have to align with the "brewtarget" project in the "Brewtarget [OSS]" organisation
# registered at https://app.signpath.io/. In some places you have to be quite pedantic about the settings (both
# here and in the SignPath account). Eg at one point we were getting the following error:
#
# "The supplied repository URL 'https://github.com/Brewtarget/brewtarget' does not match
# the expected repository URLs 'https://github.com/Brewtarget/brewtarget/'."
#
# See https://github.com/SignPath/github-action-submit-signing-request for documentation of this action (including
# parameters such as github-artifact-id). Also see https://github.com/SignPath/github-actions-extended-demo/ for
# example usage.
#
# Note that we need the special file `.signpath/artifact-configurations/default.xml` in our repository as well as
# the relevant GitHub secrets (see
# https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions).
# In particular, the repository needs to have the following secrets:
#
# SIGNPATH_API_TOKEN - As generated in app.signpath.io from the user profile page
# EXTENDED_VERIFICATION_TOKEN - This a GitHub access token to allow Signpath to access our repository
#
# See https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
# for how to create and manage GitHub access tokens
#
# We also add the following GitHub Actions variable (see
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables):
#
# SIGNPATH_ORGANIZATION_ID - Set to the organisation ID (a UUID) for "Brewtarget [OSS]" in app.signpath.io
#
# One reason not to hard code SIGNPATH_ORGANIZATION_ID is that we use its existence to signal that the above
# secrets are available -- ie that we can do the build signing. (For individual developers who have forked the
# repository, I don't think the secrets will be available so the build signing step wouldn't be possible.)
#
- name: Sign Windows binaries
if: ${{ success() && vars.SIGNPATH_ORGANIZATION_ID != '' }}
uses: signpath/github-action-submit-signing-request@v1
env:
#
# The https://app.signpath.io/ "brewtarget" project has two signing policies: "test-signing" and
# "release-signing". The former uses a self-signed certificate that can be used for testing etc. The latter
# uses a real certificate supplied by Signpath and suitable for signing released versions of the application.
#
# Ideally we would select "release-signing" policy for things we're going to release and "test-signing"
# otherwise, according to the following logic:
#
# - Currently our main branch for releasing is called "develop", but we'll probably change it to "main" in
# the not too distant future.
#
# - We don't do release branches per se, but, before we do a lot of commits for a major release, we'll
# usually cut a "stable/" branch for the prior one.
#
# NOTE however that we also want to restrict "release" signings to manually initiated builds. This is
# because, on the free tier of SignPath, all release signings need to be manually approved, and we don't want
# to be generating manual approval requests every night. (The GitHub action will time out after 10 minutes
# waiting for the approval, though we can still get the signed binary from the SignPath site if the approval
# is done later.)
#
# The syntax here is just using short-circuit evaluation to do the assignment as a one-liner.
#
SIGNPATH_SIGNING_POLICY_SLUG: |
${{ (inputs.signingType == 'release' &&
(github.ref == 'refs/heads/develop' ||
github.ref == 'refs/heads/main' ||
startsWith(github.ref, 'refs/heads/stable/'))) && 'release-signing' || 'test-signing' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ vars.SIGNPATH_ORGANIZATION_ID }}'
project-slug: 'brewtarget' # Has to match slug in https://app.signpath.io/ "brewtarget" project
signing-policy-slug: '${{ env.SIGNPATH_SIGNING_POLICY_SLUG }}'
github-artifact-id: '${{steps.upload-unsigned-artifact.outputs.artifact-id}}'
wait-for-completion: true
#
# This is "Path to where the signed artifact will be extracted. If not specified, the task will not download
# the signed artifact from SignPath."
#
# From trial and error, it seems output-artifact-directory must be a relative directory. Eg, if we set:
# output-artifact-directory: 'C:/_/mbuild/packages/windows/signed'
# We get error:
# ENOENT: no such file or directory, mkdir 'D:\a\brewtarget\brewtarget\C:\_\mbuild\packages\windows\signed'
#
output-artifact-directory: 'windows/signed'
github-extended-verification-token: '${{ secrets.EXTENDED_VERIFICATION_TOKEN }}'
#
# For now, we'll upload both the signed and unsigned
#
- name: Upload signed Windows binaries (installers)
if: ${{ success() }}
uses: actions/upload-artifact@v4
with:
name: brewtarget-dev-${{ matrix.msystem }}-signed
# Hopefully the same relative path we use in the signing step works here
path: |
windows/signed/*.*
retention-days: 7
- name: Upload CMake error info from failed build
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.msystem }}-build-windows
path: C:/_/build/
retention-days: 1
- name: Upload Meson error info from failed build
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.msystem }}-mbuild-windows
path: C:/_/mbuild/
retention-days: 1