CI, Packaging & Release
August 11, 2026 · View on GitHub
This directory holds the GitHub Actions workflows. This document also governs
src/Packaging.cmake, which lives outside this directory and
therefore will not auto-load this file — open it explicitly when touching packaging, the
Windows 7 / Qt 5 variant, or bundled OpenSSL.
See also: ../AGENTS.md (repo-wide rules, submodule push discipline) and ../src/AGENTS.md (architecture, source-wide Qt patterns).
Windows 7 variant (Qt 5.15) and OpenSSL
The win64-windows7 package is built against Qt 5.15.2, which has no Schannel TLS backend
on Windows — unlike Qt 6, which falls back to Schannel and therefore ships no OpenSSL at all.
Git sync is unaffected on both variants because libgit2 uses WinHTTP. So on Qt 5 a missing or
unloadable OpenSSL breaks exactly two things: the update check
(src/core/services/updateservice.cpp) and image hosting (src/imagehost/).
- CI builds OpenSSL 1.1.1w from source in the Qt5 job (
.github/workflows/ci-win.yml), cached under${{runner.workspace}}/openssl-1.1.1w-win64with a version-pinned key. This replaced prebuilt 1.1.1j DLLs that importedMSVCR100.dll(the VC++ 2010 runtime, absent from the package and from a clean Windows box), which is why 4.4.2's win7 build had no TLS. Qt's owntools_openssl_x64is delisted fromdownload.qt.io, and the pinned Qt 5.15.2 dlopens the literal nameslibssl-1_1-x64/libcrypto-1_1-x64, so OpenSSL 3 is not a drop-in substitute for it. - OpenSSL 1.1.1 is EOL; 1.1.1w (Sep 2023) is the final release. The variant will accrue unpatched CVEs. That is inherent to shipping Qt 5.15.2 and is only fixable by retiring the Qt 5 variant.
- Three gates, none of which replaces the others:
dumpbin /dependentson both DLLs, parsed into trimmed basenames, rejecting anyMSVCR*/MSVCP*and anything outside an explicit system + modern-runtime allowlist. This checks COMPOSITION, not content: it cannot detect a substituted DLL with the same import table. Content is pinned only by the tarball SHA-256, which is verified in the build step and therefore skipped on a cache hit.- A post-extraction check that every non-system dependency actually ships at the package root.
tools/tlsprobe— run from inside the packaged directory so it reproducesvnote.exe's real DLL load context — assertingQSslSocket::supportsSsl(). It has noinstall()rule and must never enter the package.
src/Packaging.cmaketurns the previouslyOPTIONAL(and therefore silently no-op) OpenSSL install into aFATAL_ERRORwhen the exact pair is missing on Qt 5 / Windows / x64. This runs at configure time, so a contributor building Qt 5 locally without OpenSSL opts out with-DVNOTE_REQUIRE_BUNDLED_OPENSSL=OFF(default ON, so CI is safe by default and a workflow edit cannot silently drop the gate).- The same guard asserts that
InstallRequiredSystemLibrariesactually resolved the UCRT redist. Windows 7 has no in-box UCRT, and the module's failure warnings are deliberately suppressed, so without this the omission would only surface at the last CI gate. LICENSE.OpenSSLmust remain in the package. OpenSSL 1.1.1's dual OpenSSL/SSLeay license requires reproducing the notice with binary redistribution; 4.4.2 shipped the DLLs with no notice at all. It is installed non-OPTIONALfrom-DOPENSSL_LICENSE_FILE=, keyed off whether any OpenSSL DLL is being installed rather than off the-x64names — the install globs are gated by neither Qt major nor word size, so keying it to the names would let a 32-bit Qt 5 build (or a Qt 6 build pointed at an OpenSSL dir) ship binaries with no notice.
Update artifacts
Release CI still publishes manifests, minisign signatures and delta ZIPs (see ../docs/update-signing.md). The VNote client does not consume them: it never downloads, extracts, executes or installs a release artifact, and never modifies its own install directory. These artifacts exist as the interface for a future external updater. Client-side rules: root AGENTS.md § Update Check; implementation detail: ../src/core/services/AGENTS.md § Update Check.