Skip to content

Properly enable delete action for annotations #1910

Properly enable delete action for annotations

Properly enable delete action for annotations #1910

Workflow file for this run

name: Build and Test
on:
pull_request:
push:
branches:
- '**'
tags-ignore:
# This tag is (re)created when a build on main succeeds, it'd be
# pointless to trigger yet another build in response to it.
- continuous
env:
CARGO_TERM_COLOR: always
CMAKE_COLOR_DIAGNOSTICS: ON
CLICOLOR_FORCE: 1
jobs:
test:
name: ${{ matrix.cross_os || matrix.os }} ${{ matrix.arch }}${{ matrix.component && format(' {0}', matrix.component) }} Qt ${{ matrix.qt }}${{ matrix.cross_os && format(' on {0}', matrix.os) }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
# We want to build the following:
# - Android arm32 APK
# - Android arm64 APK
# - Linux x86_64 AppImage
# - macOS x86_64 Disk Image
# - macOS arm64 Disk Image
# - Windows x86_64 Installer and ZIP including only the client
# - Windows x86_64 ZIP including server and command-line tools
# - Windows x86 Installer and ZIP including only the client
# Android targets are cross-compiled from Linux. We use the oldest Ubuntu
# version available for compatibility reasons, since glibc is not included
# in the AppImage. On Windows, the server and command-line tools are split
# off into their own package because Windows Defender randomly misdetects
# the executables as something bad. This can be fixed by submitting the
# executables to Microsoft and they seem to remove the bogus detection
# pretty quickly, but having them separated means we don't need to make
# client releases dependent on them getting around to that when it's only
# a secondary executable that's causing it.
matrix:
# There's ways to deduplicate these includes, but any mistake causes
# utterly confounding errors, so just explicitly specify each target.
include:
- os: ubuntu-20.04
cross_os: ''
component: ''
qt: 5.15.14
arch: x86_64
sccache_triplet: x86_64-unknown-linux-musl
build_flags: -DINITSYS=systemd -DBUILD_PACKAGE_SUFFIX=x86_64 -G Ninja
# This causes the AppImage to be generated, instead of just creating
# the portable tree, because there seems to be no way to separate
# these steps with linuxdeploy
# Even though the svg component is linked explicitly,
# linuxdeploy-plugin-qt does not seem to notice and so does not
# export the iconengine if it is not told that we really, really
# want svg plugins please
packager: >-
EXTRA_QT_PLUGINS="svg;"
VERSION="${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '$(git describe)' }}"
cmake --install build --config Release
# The runner has multiple clang versions installed and CMake/Qt gets
# confused about which one to pick for some reason, so this also
# sets Clang_ROOT during the Qt build
qt_pre_build: >
sudo apt-get update &&
sudo apt-get install --no-install-recommends
libatspi2.0-dev libmtdev-dev libts-dev libgtk-3-dev
libgl1-mesa-dev libglu1-mesa-dev libxi-dev libdrm-dev
libgbm-dev libgl-dev libgles-dev libegl-dev libegl1-mesa-dev
libxext-dev libxfixes-dev libxrender-dev libx11-dev
libxcb1-dev libx11-xcb-dev libxcb-glx0-dev libxcb-util0-dev
libxkbcommon-dev libxkbcommon-x11-dev libxcb-keysyms1-dev
libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev
libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev
libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev
libxcb-util-dev libinput-dev libvulkan-dev
libxcb-xinerama0-dev libxcb-xkb-dev libxcb-xinput-dev libclang-12-dev
libasound2-dev libpulse-dev libcups2-dev libssl-dev
libfontconfig1-dev &&
echo "Clang_ROOT=/usr/lib/llvm-12" >> $GITHUB_ENV
other_pre_build: >
sudo apt-get update &&
sudo apt-get install --no-install-recommends
libsecret-1-dev
- os: ubuntu-20.04
cross_os: Android
component: ''
qt: 5.15.14
arch: arm64
sccache_triplet: x86_64-unknown-linux-musl
packager: cmake --install build --config Release --prefix .
cross_qt_args: >-
"-DANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
"-DANDROID_NDK_ROOT=$ANDROID_NDK_ROOT"
"-DANDROID_HOST_PATH=$GITHUB_WORKSPACE/.github/deps/qt"
-DANDROID_ABI=arm64-v8a
cross_other_args: >-
"-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake"
"-DANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
"-DANDROID_NDK_ROOT=$ANDROID_NDK_ROOT"
-DANDROID_PLATFORM=android-23
-DANDROID_ABI=arm64-v8a
build_flags: >-
"-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake"
-DANDROID_PLATFORM=android-23
-DANDROID_ABI=arm64-v8a
-DANDROID_SDK_PLATFORM=android-31
-DANDROID_SDK_BUILD_TOOLS_REVISION=34.0.0
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=on
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=BOTH
# The runner has multiple clang versions installed and CMake/Qt gets
# confused about which one to pick for some reason, so this also
# sets Clang_ROOT during the Qt build
qt_pre_build: >
sudo apt-get update &&
sudo apt-get install --no-install-recommends
libatspi2.0-dev libmtdev-dev libts-dev libgtk-3-dev
libgl1-mesa-dev libglu1-mesa-dev libxi-dev libdrm-dev
libgbm-dev libgl-dev libgles-dev libegl-dev libegl1-mesa-dev
libxext-dev libxfixes-dev libxrender-dev libx11-dev
libxcb1-dev libx11-xcb-dev libxcb-glx0-dev libxcb-util0-dev
libxkbcommon-dev libxkbcommon-x11-dev libxcb-keysyms1-dev
libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev
libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev
libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev
libxcb-util-dev libinput-dev libvulkan-dev
libxcb-xinerama0-dev libxcb-xkb-dev libxcb-xinput-dev libclang-12-dev
libasound2-dev libpulse-dev libcups2-dev libssl-dev
libfontconfig1-dev &&
echo "Clang_ROOT=/usr/lib/llvm-12" >> $GITHUB_ENV
other_pre_build: >
sudo apt-get update &&
sudo apt-get install --no-install-recommends
libsecret-1-dev
- os: ubuntu-20.04
cross_os: Android
component: ''
qt: 5.15.14
arch: arm32
sccache_triplet: x86_64-unknown-linux-musl
packager: cmake --install build --config Release --prefix .
cross_qt_args: >-
"-DANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
"-DANDROID_NDK_ROOT=$ANDROID_NDK_ROOT"
"-DANDROID_HOST_PATH=$GITHUB_WORKSPACE/.github/deps/qt"
-DANDROID_ABI=armeabi-v7a
cross_other_args: >-
"-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake"
"-DANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
"-DANDROID_NDK_ROOT=$ANDROID_NDK_ROOT"
-DANDROID_PLATFORM=android-23
-DANDROID_ABI=armeabi-v7a
build_flags: >-
"-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake"
-DANDROID_PLATFORM=android-23
-DANDROID_ABI=armeabi-v7a
-DANDROID_SDK_PLATFORM=android-31
-DANDROID_SDK_BUILD_TOOLS_REVISION=34.0.0
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=on
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=BOTH
# The runner has multiple clang versions installed and CMake/Qt gets
# confused about which one to pick for some reason, so this also
# sets Clang_ROOT during the Qt build
qt_pre_build: >
sudo apt-get update &&
sudo apt-get install --no-install-recommends
libatspi2.0-dev libmtdev-dev libts-dev libgtk-3-dev
libgl1-mesa-dev libglu1-mesa-dev libxi-dev libdrm-dev
libgbm-dev libgl-dev libgles-dev libegl-dev libegl1-mesa-dev
libxext-dev libxfixes-dev libxrender-dev libx11-dev
libxcb1-dev libx11-xcb-dev libxcb-glx0-dev libxcb-util0-dev
libxkbcommon-dev libxkbcommon-x11-dev libxcb-keysyms1-dev
libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev
libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev
libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev
libxcb-util-dev libinput-dev libvulkan-dev
libxcb-xinerama0-dev libxcb-xkb-dev libxcb-xinput-dev libclang-12-dev
libasound2-dev libpulse-dev libcups2-dev libssl-dev
libfontconfig1-dev &&
echo "Clang_ROOT=/usr/lib/llvm-12" >> $GITHUB_ENV
other_pre_build: >
sudo apt-get update &&
sudo apt-get install --no-install-recommends
libsecret-1-dev
- os: macos-13
cross_os: ''
component: ''
qt: 6.7.2
arch: x86_64
build_flags: -DBUILD_PACKAGE_SUFFIX=x86_64 -G Ninja
sccache_triplet: x86_64-apple-darwin
packager: cpack --verbose --config build/CPackConfig.cmake -C Release
- os: macos-14
cross_os: ''
component: ''
qt: 6.7.2
arch: arm64
build_flags: -DBUILD_PACKAGE_SUFFIX=arm64 -G Ninja
sccache_triplet: aarch64-apple-darwin
packager: cpack --verbose --config build/CPackConfig.cmake -C Release
- os: windows-latest
cross_os: ''
component: ''
qt: 5.15.14
arch: x86_64
sccache_triplet: x86_64-pc-windows-msvc
build_flags: -DBUILD_PACKAGE_SUFFIX=x86_64 -G Ninja
qt_pre_build: >
choco install gperf jom winflexbison3 &&
New-Item -Path C:\ProgramData\Chocolatey\bin\flex.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_flex.exe &&
New-Item -Path C:\ProgramData\Chocolatey\bin\bison.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_bison.exe
# Copying files is a disgusting hack because windeployqt does not
# search PATH to find DLLs and it gets confused by QtKeychain having
# a Qt prefix and thinks it is part of Qt and tries to process it
# and fails if it is not in the Qt bin directory with the rest of
# them
packager: >
cp .github/deps/other/bin/qt*.dll .github/deps/qt/bin &&
cpack --verbose --config build/CPackConfig.cmake -C Release
- os: windows-latest
cross_os: ''
component: 'Tools'
qt: 5.15.14
arch: x86_64
sccache_triplet: x86_64-pc-windows-msvc
build_flags: -DBUILD_PACKAGE_SUFFIX=x86_64 -G Ninja
qt_pre_build: >
choco install gperf jom winflexbison3 &&
New-Item -Path C:\ProgramData\Chocolatey\bin\flex.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_flex.exe &&
New-Item -Path C:\ProgramData\Chocolatey\bin\bison.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_bison.exe
# Copying files is a disgusting hack because windeployqt does not
# search PATH to find DLLs and it gets confused by QtKeychain having
# a Qt prefix and thinks it is part of Qt and tries to process it
# and fails if it is not in the Qt bin directory with the rest of
# them
packager: >
cp .github/deps/other/bin/qt*.dll .github/deps/qt/bin &&
cpack --verbose --config build/CPackConfig.cmake -C Release
- os: windows-latest
qt: 5.15.14
arch: x86
sccache_triplet: x86_64-pc-windows-msvc
build_flags: -DCARGO_TRIPLE=i686-pc-windows-msvc -DBUILD_PACKAGE_SUFFIX=x86 -G Ninja
qt_pre_build: >
choco install gperf jom winflexbison3 &&
New-Item -Path C:\ProgramData\Chocolatey\bin\flex.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_flex.exe &&
New-Item -Path C:\ProgramData\Chocolatey\bin\bison.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_bison.exe
# Copying files is a disgusting hack because windeployqt does not
# search PATH to find DLLs and it gets confused by QtKeychain having
# a Qt prefix and thinks it is part of Qt and tries to process it
# and fails if it is not in the Qt bin directory with the rest of
# them
packager: >
cp .github/deps/other/bin/qt*.dll .github/deps/qt/bin &&
cpack --verbose --config build/CPackConfig.cmake -C Release
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0 # for git-describe
submodules: true
- name: Install Ninja on macOS
run: |
brew install ninja
if: runner.os == 'macOS'
- name: Activate MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
arch: win${{ matrix.arch == 'x86_64' && '64' || '32' }}
if: runner.os == 'Windows'
- name: Install NASM for building OpenSSL in Windows
uses: ilammy/setup-nasm@v1
with:
platform: win${{ matrix.arch == 'x86_64' && '64' || '32' }}
if: runner.os == 'Windows'
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: x${{ matrix.arch == 'x86_64' && '64' || '32' }}
if: runner.os == 'Windows'
- name: Work around QTBUG-112465
run: |
# Moving directories is faster than deleting everything inside them
mv ${ANDROID_SDK_ROOT}/platforms/{android-*-*,..}
ls "${ANDROID_SDK_ROOT}/platforms"
shell: bash
if: matrix.cross_os == 'Android'
- name: Configure Linux system dependencies
uses: ./.github/actions/restore-linux
if: runner.os == 'Linux'
- name: Build dependencies
uses: ./.github/actions/build-deps
id: deps
with:
cache_key: ${{ runner.os }}-${{ matrix.arch }}
path: .github/deps
target_arch: "${{ matrix.arch }}"
qt: ${{ matrix.qt }}
qt_pre_build: ${{ matrix.qt_pre_build }}
qt_args: ${{ matrix.qt_args }}
other_pre_build: ${{ matrix.other_pre_build }}
other_args: ${{ matrix.other_args }}
if: '!matrix.cross_os'
- name: Build cross-compiler dependencies
uses: ./.github/actions/build-deps
id: cross-deps
with:
cache_key: ${{ runner.os }}+${{ matrix.cross_os }}-${{ matrix.arch }}
path: .github/cross-deps
target_arch: "${{ matrix.arch }}"
qt: ${{ matrix.qt }}
qt_pre_build: ${{ matrix.cross_qt_pre_build }}
qt_args: ${{ matrix.cross_qt_args }}
other_pre_build: ${{ matrix.cross_other_pre_build }}
other_args: ${{ matrix.cross_other_args }}
if: matrix.cross_os
- name: Set up compiler cache
uses: ./.github/actions/pre-sccache
id: sccache
with:
triplet: ${{ matrix.sccache_triplet }}
cache_key: ${{ runner.os }}${{ matrix.component }}-${{ matrix.arch }}${{ matrix.cross_os && format('+{0}', matrix.cross_os) }}-${{ matrix.qt }}
- name: Cache gradle
uses: actions/cache@v4
with:
# The zip file is unnecessary but the .zip.ok file is needed or it
# will blow away the installation and redownload everything
path: |-
~/.gradle/wrapper/dists/gradle-*/*/gradle-*
!~/.gradle/wrapper/dists/gradle-*/*/gradle-*.zip
key: gradle-${{ runner.os }}-${{ matrix.arch }}+${{ matrix.cross_os }}-${{ matrix.qt }}
if: matrix.cross_os == 'Android'
- name: Prepare Windows signing
run: |
if ($env:WINDOWS_CERTIFICATE) {
New-Item -ItemType directory -Path "$env:GITHUB_WORKSPACE/wincert"
Set-Content -Path "$env:GITHUB_WORKSPACE/wincert/drawpile.txt" -Value $env:WINDOWS_CERTIFICATE
certutil -decode "$env:GITHUB_WORKSPACE/wincert/drawpile.txt" "$env:GITHUB_WORKSPACE/wincert/drawpile.pfx"
Remove-Item -Path "$env:GITHUB_WORKSPACE/wincert/drawpile.txt"
echo "WINDOWS_PFX_PATH=$env:GITHUB_WORKSPACE/wincert/drawpile.pfx" >>$env:GITHUB_ENV
}
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
if: runner.os == 'Windows'
- name: Generate project
run: >
cmake -S . -B build --log-level=VERBOSE
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_C_COMPILER_LAUNCHER=sccache
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
-DCMAKE_OBJC_COMPILER_LAUNCHER=sccache
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=sccache
-DCLIENT=${{ matrix.component == 'Tools' && 'off' || 'on' }}
-DSERVER=${{ runner.os == 'Windows' && !matrix.component && 'off' || 'on' }}
-DSERVERGUI=${{ runner.os == 'Windows' && !matrix.component && 'off' || 'on' }}
-DTOOLS=${{ runner.os == 'Windows' && !matrix.component && 'off' || 'on' }}
-DTESTS=on
-DUSE_GENERATORS=off
"-DCMAKE_PREFIX_PATH=${{ matrix.cross_os && format('{0};', steps.cross-deps.outputs.path) }}${{ steps.deps.outputs.path }}"
-DCMAKE_INSTALL_PREFIX=out
-DCLANG_TIDY=off
-DDIST_BUILD=${{ matrix.packager && 'on' }}
-DSOURCE_ASSETS=off
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=${{
matrix.packager
&& startsWith(github.ref, 'refs/tags/')
&& 'on'
}}
-DBUILD_VERSION='${{
matrix.packager
&& startsWith(github.ref, 'refs/tags/')
&& github.ref_name
}}'
-DBUILD_PACKAGE_COMPONENT='${{ matrix.component }}'
${{ matrix.build_flags }}
- name: Prepare APK signing
run: |
if [ -n "$ANDROID_KEYSTORE" ] && [ -n "$ANDROID_KEYSTORE_PASS" ]; then
keystore_path="$GITHUB_WORKSPACE/drawpile.keystore"
echo "$ANDROID_KEYSTORE" | base64 -d > "$keystore_path"
echo QT_ANDROID_KEYSTORE_PATH="$keystore_path" >> "$GITHUB_ENV"
fi
env:
ANDROID_KEYSTORE: ${{ secrets.ANDROID_KEYSTORE }}
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
if: matrix.cross_os == 'Android' && matrix.packager
- name: Build project
run: cmake --build build --parallel $(nproc || sysctl -n hw.ncpu || echo 2) --config Release
env:
RUSTC_WRAPPER: sccache
SCCACHE_CACHE_SIZE: 200M
SCCACHE_DIR: ${{ steps.sccache.outputs.path }}/cache
QT_ANDROID_KEYSTORE_ALIAS: drawpile
QT_ANDROID_KEYSTORE_STORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
WINDOWS_PFX_PASS: ${{ secrets.WINDOWS_CERTIFICATE_PASS }}
WINDOWS_PFX_TIMESTAMP_URL: 'http://timestamp.digicert.com'
- name: Run C++ tests
run: ctest -C Release --output-on-failure
working-directory: build
if: '!matrix.cross_os'
- name: Run packaging
run: ${{ matrix.packager }}
env:
WINDOWS_PFX_PASS: ${{ secrets.WINDOWS_CERTIFICATE_PASS }}
WINDOWS_PFX_TIMESTAMP_URL: 'http://timestamp.digicert.com'
if: matrix.packager
- name: Upload artifact
uses: actions/upload-artifact@v4
if: matrix.packager
with:
name: Drawpile${{ matrix.component && format('-{0}', matrix.component) }}-${{ matrix.cross_os || runner.os }}-${{ matrix.arch }}-Qt${{ matrix.qt }}
path: |
Drawpile-*.AppImage
Drawpile-*.apk
Drawpile-*.dmg
Drawpile-*.msi
Drawpile-*.zip
- name: Upload error logs and artefacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: Logs${{ matrix.component && format('-{0}', matrix.component) }}-${{ matrix.cross_os || runner.os }}-${{ matrix.arch }}-Qt${{ matrix.qt }}
path: |
**/*.log
**/*.wxs
build/android-build/*.properties
build/android_deployment_settings.json
- name: Save sccache
uses: ./.github/actions/post-sccache
with:
cache-hit: ${{ steps.sccache.outputs.cache-hit }}
cache_key: ${{ steps.sccache.outputs.cache_key }}
if: success() || failure()
continue-on-error: true
- name: sccache stats
run: sccache --show-stats
if: success() || failure()
continue-on-error: true
release:
needs: test
runs-on: ubuntu-20.04
if: >
success() && (
github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|| startsWith(github.ref, 'refs/tags/'))
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Dump directory contents
run: ls -alFR
- name: Check out code
uses: actions/checkout@v4
with:
path: checkout
- name: Collect release notes
if: startsWith(github.ref, 'refs/tags/')
run: awk -v RS='' '/^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2} Version ${{ github.ref_name }}/,/^[[:digit:]]/' checkout/ChangeLog | tail '+2' > release-description
- name: Write continuous release description
if: "!startsWith(github.ref, 'refs/tags/')"
env:
RELEASE_DESCRIPTION: >
This release is an automatically generated snapshot of the current
state of development. It is continuously updated with
work-in-progress changes that may be broken, incomplete, or
incompatible with other versions of Drawpile. For downloads, take a
look at the Assets below.
Unless you really, really know what you're doing, **pick the 64bit
options**. 32bit is probably *not* what you want unless you have a
very strange device.
run:
echo "$RELEASE_DESCRIPTION" > release-description
- name: Create release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET_COMMIT: ${{ github.sha }}
RELEASE_DESCRIPTION_FILE: release-description
RELEASE_NAME: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || 'continuous' }}
CLOBBER_EXISTING: ${{ !startsWith(github.ref, 'refs/tags/') }}
PRERELEASE: ${{ !startsWith(github.ref, 'refs/tags/') || contains(github.ref, '-') }}
run: |
checkout/pkg/make-github-release.sh \
'Drawpile-Android-arm64-Qt5.15.14;Drawpile-*.apk;Android APK 64bit' \
'Drawpile-Linux-x86_64-Qt5.15.14;Drawpile-*.AppImage;Linux AppImage 64bit' \
'Drawpile-macOS-x86_64-Qt6.7.2;Drawpile-*.dmg;macOS Disk Image for Intel' \
'Drawpile-macOS-arm64-Qt6.7.2;Drawpile-*.dmg;macOS Disk Image for Apple Silicon' \
'Drawpile-Windows-x86_64-Qt5.15.14;Drawpile-*.msi;Windows Installer 64bit' \
'Drawpile-Windows-x86_64-Qt5.15.14;Drawpile-*.zip;Windows Portable ZIP 64bit' \
'Drawpile-Tools-Windows-x86_64-Qt5.15.14;Drawpile-*.zip;Windows Server and Tools Portable ZIP 64bit - does not include Drawpile' \
'Drawpile-Android-arm32-Qt5.15.14;Drawpile-*.apk;Android APK 32bit - do not use, you want 64bit' \
'Drawpile-Windows-x86-Qt5.15.14;Drawpile-*.msi;Windows Installer 32bit - do not use, you want 64bit' \
'Drawpile-Windows-x86-Qt5.15.14;Drawpile-*.zip;Windows Portable ZIP 32bit - do not use, you want 64bit'