Skip to content

WIP: Test SignPath errors #2287

WIP: Test SignPath errors

WIP: Test SignPath errors #2287

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: 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
build_type: RelWithDebInfo
collect_symbols: true
signpath: true
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
ffmpeg_pre_build: >
choco install yasm
# 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 RelWithDebInfo
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 ffmpeg in macOS
run: |
brew install nasm
if: runner.os == 'macOS'
- name: Install NASM for building OpenSSL and ffmpeg in Windows
uses: ilammy/setup-nasm@v1
with:
platform: win${{ matrix.arch == 'x86_64' && '64' || '32' }}
if: runner.os == 'Windows'
- name: Install YASM for building libvpx in macOS
run: |
brew install yasm
if: runner.os == 'macOS'
- name: Install pkg-config for building and linking to ffmpeg in Windows
run: |
choco install pkgconfiglite
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: Set Android environment variables
run: |
build_tools_version=34.0.0-rc3
ndk_version=27.0.12077973
target_sdk_version=34
ndk_root="$ANDROID_SDK_ROOT/ndk/$ndk_version"
ndk_toolchain_file="$ndk_root/build/cmake/android.toolchain.cmake"
platform="android-$target_sdk_version"
echo "ANDROID_BUILD_TOOLS_VERSION=$build_tools_version" >> "$GITHUB_ENV"
echo "ANDROID_NDK_VERSION=$ndk_version" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ndk_root" >> "$GITHUB_ENV"
echo "ANDROID_NDK_TOOLCHAIN_FILE=$ndk_toolchain_file" >> "$GITHUB_ENV"
echo "ANDROID_PLATFORM=$platform" >> "$GITHUB_ENV"
echo "ANDROID_TARGET_SDK_VERSION=$target_sdk_version" >> "$GITHUB_ENV"
if: matrix.cross_os == 'Android'
# Qt's build toolage really likes to auto-detect Android package
# versions, despite all attempts to specify them explicitly. So we
# uninstall all the packages we don't need to avoid that happening.
- name: Install correct Android SDK packages, remove wrong ones
run: |
sdkmanager="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager"
packages_to_uninstall="$("$sdkmanager" --list_installed 2>&1 | perl -nae 'print "$F[0]\n" if $F[0] =~ /^(build-tools|ndk|platforms);/ && $F[0] ne "build-tools;$ENV{ANDROID_BUILD_TOOLS_VERSION}" && $F[0] ne "ndk;$ENV{ANDROID_NDK_VERSION}" && $F[0] ne "platforms;$ENV{ANDROID_PLATFORM}"')"
echo
echo "Packages to uninstall:"
echo "$packages_to_uninstall" | perl -pe 's/^/ * /'
echo
if [ -n "$packages_to_uninstall" ]; then
echo "$packages_to_uninstall" | xargs "$sdkmanager" --uninstall
fi
set -x
yes | "$sdkmanager" "build-tools;$ANDROID_BUILD_TOOLS_VERSION" "ndk;$ANDROID_NDK_VERSION" "platforms;$ANDROID_PLATFORM"
if: matrix.cross_os == 'Android'
# This check is here to make sure the Java version doesn't change from
# under us. Both 11 and 17 should be okay for android-34. Lower and
# higher versions are known broken. Anything in-between is not LTS.
- name: Check Java version
run: |
java_version_output="$(java -version 2>&1)"
echo "$java_version_output"
java_version="$(echo "$java_version_output" | perl -0777 -ne '/version\s+"([0-9]+)\./ && print $1')"
expected_java_version='11'
if [ "$java_version" = "$expected_java_version" ]; then
echo "Java version $java_version matches expected version $expected_java_version"
else
echo "Java version $java_version does NOT match expected version $expected_java_version" 1>&2
exit 1
fi
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:
build_type: ${{ matrix.build_type }}
cache_key: ${{ matrix.build_type != 'Release' && format('{0}-', matrix.build_type) || '' }}${{ 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 }}
ffmpeg_pre_build: ${{ matrix.ffmpeg_pre_build }}
ffmpeg_args: ${{ matrix.ffmpeg_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:
build_type: ${{ matrix.build_type }}
cache_key: ${{ matrix.build_type != 'Release' && format('{0}-', matrix.build_type) || '' }}${{ 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 }}
ffmpeg_pre_build: ${{ matrix.cross_ffmpeg_pre_build }}
ffmpeg_args: ${{ matrix.cross_ffmpeg_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: ${{ matrix.build_type != 'Release' && format('{0}-', matrix.build_type) || '' }}${{ 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 local Windows signing for builds not using SignPath
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' && matrix.packager && !matrix.signpath
- name: Figure out Windows product version from build version
run: >
cmake
"-DBUILD_VERSION=${{ github.ref_name }}"
"-DOUTPUT_PATH=$env:GITHUB_ENV"
"-DSEARCH_PATHS=${{ matrix.cross_os && format('{0};', steps.cross-deps.outputs.path) }}${{ steps.deps.outputs.path }}"
-P ".github/scripts/build-to-product-version.cmake"
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Install rcedit to set PE metadata on Windows
run: |
choco install rcedit
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Set PE metadata of dependencies on Windows
run: >
cmake
"-DPRODUCT_NAME=Drawpile client"
"-DPRODUCT_VERSION=$env:WINDOWS_PRODUCT_VERSION"
"-DSEARCH_PATHS=${{ matrix.cross_os && format('{0};', steps.cross-deps.outputs.path) }}${{ steps.deps.outputs.path }}"
-P ".github/scripts/edit-pe-metadata.cmake"
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Generate project
run: >
cmake -S . -B build --log-level=VERBOSE
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-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 ${{ matrix.build_type }}
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: Set PE metadata built files on Windows
run: >
cmake
"-DPRODUCT_NAME=Drawpile client"
"-DPRODUCT_VERSION=$env:WINDOWS_PRODUCT_VERSION"
"-DSEARCH_PATHS=build"
-P ".github/scripts/edit-pe-metadata.cmake"
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Run C++ tests
run: ctest -C ${{ matrix.build_type }} --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 artifacts for SignPath to sign
uses: actions/upload-artifact@v4
id: signpath-upload
with:
name: SignPath${{ matrix.component && format('-{0}', matrix.component) }}-${{ matrix.cross_os || runner.os }}-${{ matrix.arch }}-Qt${{ matrix.qt }}
path: |
Drawpile-*.msi
Drawpile-*.zip
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Delete unsigned artifacts
id: signpath-delete-unsigned
shell: bash
run: rm -vf Drawpile-*.msi Drawpile-*.zip
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Submit artifacts to SignPath to sign
uses: signpath/github-action-submit-signing-request@v1
id: signpath-sign
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ secrets.SIGNPATH_ORGANIZATION_ID }}'
project-slug: 'Drawpile'
signing-policy-slug: 'test-signing'
artifact-configuration-slug: 'client'
github-artifact-id: '${{ steps.signpath-upload.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
parameters: |
version: "${{ github.ref_name }}"
productname: "Drawpile client"
productversion: "${{ env.WINDOWS_PRODUCT_VERSION }}"
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Delete unsigned artifacts uploaded for SignPath after signing
uses: actions/github-script@v7
id: signpath-delete-uploaded
with:
script: |
github.rest.actions.deleteArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: ${{ steps.signpath-upload.outputs.artifact-id }}
});
if: runner.os == 'Windows' && matrix.packager && matrix.signpath
- name: Bundle PDBs
run: >
cmake "-DEXE_SEARCH_PATHS=build"
"-DDLL_SEARCH_PATHS=${{ matrix.cross_os && steps.cross-deps.outputs.path || steps.deps.outputs.path }}"
-P .github/scripts/bundle-pdbs.cmake
if: runner.os == 'Windows' && matrix.collect_symbols
- 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
DrawpileSymbols-*.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/build.gradle
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: |
echo '**Code signing policy:** <https://drawpile.net/codesigningpolicy/>' > release-description
echo >> release-description
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-Windows-x86_64-Qt5.15.14;DrawpileSymbols-*.zip;Debug Symbols for Windows 64bit - does not include Drawpile' \
'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'