[ci] add SignPath Windows test signing

This commit is contained in:
dijunkun
2026-08-08 01:50:47 +08:00
parent e6c26511cd
commit 21eee5ccdc
15 changed files with 278 additions and 2 deletions
+62
View File
@@ -13,8 +13,14 @@ on:
description: "Hotfix patch number, for example 1 or 2. Use 0 for a normal build."
required: false
default: "0"
sign_windows_test:
description: "Submit the Windows installer to SignPath using test-signing."
required: false
type: boolean
default: false
permissions:
actions: read
contents: write
env:
@@ -410,6 +416,52 @@ jobs:
run: |
& "${{ github.workspace }}\scripts\windows\pkg_x64.ps1" $env:VERSION_NUM
- name: Upload unsigned Windows installer for test signing
if: github.event_name == 'workflow_dispatch' && inputs.sign_windows_test
id: upload-unsigned-windows-installer
uses: actions/upload-artifact@v7
with:
path: ${{ github.workspace }}/scripts/windows/crossdesk-win-x64-${{ env.VERSION_NUM }}.exe
archive: false
if-no-files-found: error
retention-days: 1
- name: Sign Windows installer with SignPath test certificate
if: github.event_name == 'workflow_dispatch' && inputs.sign_windows_test
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
organization-id: ${{ vars.SIGNPATH_ORGANIZATION_ID }}
project-slug: crossdesk
signing-policy-slug: test-signing
github-artifact-id: ${{ steps.upload-unsigned-windows-installer.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: ${{ github.workspace }}\signpath\signed-installer
skip-decompress: true
parameters: |
version: ${{ toJSON(env.VERSION_NUM) }}
- name: Verify and use test-signed Windows installer
if: github.event_name == 'workflow_dispatch' && inputs.sign_windows_test
shell: pwsh
run: |
$installerName = "crossdesk-win-x64-${{ env.VERSION_NUM }}.exe"
$signedInstaller = Join-Path "${{ github.workspace }}\signpath\signed-installer" $installerName
$destination = Join-Path "${{ github.workspace }}\scripts\windows" $installerName
if (!(Test-Path $signedInstaller)) {
throw "SignPath did not return the signed installer: $signedInstaller"
}
$signature = Get-AuthenticodeSignature $signedInstaller
if (!$signature.SignerCertificate -or $signature.Status -eq "NotSigned") {
throw "SignPath returned an installer without an Authenticode signature."
}
Write-Host "Signer: $($signature.SignerCertificate.Subject)"
Write-Host "Signature status: $($signature.Status)"
Copy-Item $signedInstaller $destination -Force
- name: Build Portable CrossDesk
run: |
xmake f --CROSSDESK_VERSION=${{ env.VERSION_NUM }} --USE_CUDA=true --CROSSDESK_PORTABLE=true -y
@@ -544,6 +596,10 @@ jobs:
body: |
Binary release only. Source code is not included.
## Code signing policy
Free code signing provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/).
- name: Create or update 'latest' tag
run: |
git config user.name "github-actions[bot]"
@@ -560,6 +616,12 @@ jobs:
prerelease: false
files: release/*
generate_release_notes: false
body: |
Binary release only. Source code is not included.
## Code signing policy
Free code signing provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/).
- name: Upload artifacts to server
uses: burnett01/rsync-deployments@5.2
+8
View File
@@ -10,6 +10,14 @@
[![GitHub stars](https://img.shields.io/github/stars/kunkundi/crossdesk.svg?style=social)]()
[![GitHub forks](https://img.shields.io/github/forks/kunkundi/crossdesk.svg?style=social)]()
## Code signing policy
Free code signing provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/).
- Committers and reviewers: [kunkundi](https://github.com/kunkundi)
- Approvers: [kunkundi](https://github.com/kunkundi)
- Privacy policy: CrossDesk will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it.
[ [English](README_EN.md) / 中文 ]
PC 客户端
+8
View File
@@ -10,6 +10,14 @@
[![GitHub stars](https://img.shields.io/github/stars/kunkundi/crossdesk.svg?style=social)]()
[![GitHub forks](https://img.shields.io/github/forks/kunkundi/crossdesk.svg?style=social)]()
## Code signing policy
Free code signing provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/).
- Committers and reviewers: [kunkundi](https://github.com/kunkundi)
- Approvers: [kunkundi](https://github.com/kunkundi)
- Privacy policy: CrossDesk will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it.
[ [中文](README.md) / English ]
PC Client
+5
View File
@@ -9,3 +9,8 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "crossdesk_debug.manifest"
#else
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "crossdesk.manifest"
#endif
#define CROSSDESK_FILE_DESCRIPTION "CrossDesk"
#define CROSSDESK_ORIGINAL_FILENAME "CrossDesk.exe"
#include "version_info.rcinc"
+5
View File
@@ -6,3 +6,8 @@ IDI_ICON1 ICON "..\\..\\icons\\windows\\crossdesk.ico"
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "crossdesk_portable.manifest"
#define CROSSDESK_FILE_DESCRIPTION "CrossDesk Portable"
#define CROSSDESK_ORIGINAL_FILENAME "CrossDesk.exe"
#include "version_info.rcinc"
+4
View File
@@ -0,0 +1,4 @@
#define CROSSDESK_FILE_DESCRIPTION "CrossDesk Service"
#define CROSSDESK_ORIGINAL_FILENAME "crossdesk_service.exe"
#include "version_info.rcinc"
@@ -0,0 +1,18 @@
// Session helper icon and manifest resources.
IDI_ICON1 ICON "..\\..\\icons\\windows\\crossdesk.ico"
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
#ifdef CROSSDESK_PORTABLE
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "crossdesk_portable.manifest"
#elif defined(CROSSDESK_DEBUG)
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "crossdesk_debug.manifest"
#else
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "crossdesk.manifest"
#endif
#define CROSSDESK_FILE_DESCRIPTION "CrossDesk Session Helper"
#define CROSSDESK_ORIGINAL_FILENAME "crossdesk_session_helper.exe"
#include "version_info.rcinc"
+9
View File
@@ -4,6 +4,7 @@
; Installer initial constants
!define PRODUCT_NAME "CrossDesk"
!define PRODUCT_VERSION "${VERSION}"
!define PRODUCT_VERSION_NUMERIC "${VERSION_NUMERIC}"
!define PRODUCT_PUBLISHER "CrossDesk"
!define PRODUCT_WEB_SITE "https://www.crossdesk.cn/"
!define APP_NAME "CrossDesk"
@@ -41,6 +42,14 @@ RequestExecutionLevel admin
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "crossdesk-win-x64-${PRODUCT_VERSION}.exe"
VIProductVersion "${PRODUCT_VERSION_NUMERIC}"
VIAddVersionKey /LANG=2052 "CompanyName" "CrossDesk"
VIAddVersionKey /LANG=2052 "FileDescription" "CrossDesk Installer"
VIAddVersionKey /LANG=2052 "FileVersion" "${PRODUCT_VERSION}"
VIAddVersionKey /LANG=2052 "LegalCopyright" "Copyright (C) CrossDesk contributors"
VIAddVersionKey /LANG=2052 "OriginalFilename" "crossdesk-win-x64-${PRODUCT_VERSION}.exe"
VIAddVersionKey /LANG=2052 "ProductName" "${PRODUCT_NAME}"
VIAddVersionKey /LANG=2052 "ProductVersion" "${PRODUCT_VERSION}"
InstallDir "$PROGRAMFILES\CrossDesk"
InstallDirRegKey HKCU "Software\${PRODUCT_NAME}" "InstallDir"
ShowInstDetails show
+29 -1
View File
@@ -26,12 +26,40 @@ function Normalize-AppVersion {
return $InputVersion
}
function Convert-To-WindowsVersion {
param(
[Parameter(Mandatory = $true)]
[string]$InputVersion
)
$body = $InputVersion -replace '^v', ''
$baseMatch = [regex]::Match($body, '^[0-9]+(?:\.[0-9]+){0,3}')
if (!$baseMatch.Success) {
return "0.0.0.0"
}
$parts = [System.Collections.Generic.List[int]]::new()
foreach ($part in $baseMatch.Value.Split('.')) {
$value = [int]$part
if ($value -gt 65535) {
$value = 0
}
$parts.Add($value)
}
while ($parts.Count -lt 4) {
$parts.Add(0)
}
return ($parts -join '.')
}
$normalizedVersion = Normalize-AppVersion -InputVersion $Version
$windowsVersion = Convert-To-WindowsVersion -InputVersion $normalizedVersion
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Push-Location $scriptDir
try {
& makensis "/DVERSION=$normalizedVersion" "nsis_script.nsi"
& makensis "/DVERSION=$normalizedVersion" "/DVERSION_NUMERIC=$windowsVersion" "nsis_script.nsi"
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1">
<parameters>
<parameter name="version" required="true" />
</parameters>
<pe-file path="crossdesk-win-x64-${version}.exe"
product-name="CrossDesk"
product-version="${version}"
file-version="${version}"
company-name="CrossDesk"
copyright="Copyright (C) CrossDesk contributors"
original-filename="crossdesk-win-x64-${version}.exe">
<authenticode-sign />
</pe-file>
</artifact-configuration>
+54
View File
@@ -0,0 +1,54 @@
#include <winver.h>
#ifndef CROSSDESK_VERSION_STRING
#define CROSSDESK_VERSION_STRING "0.0.0"
#endif
#ifndef CROSSDESK_VERSION_NUMERIC
#define CROSSDESK_VERSION_NUMERIC 0,0,0,0
#endif
#ifndef CROSSDESK_FILE_DESCRIPTION
#define CROSSDESK_FILE_DESCRIPTION "CrossDesk"
#endif
#ifndef CROSSDESK_ORIGINAL_FILENAME
#define CROSSDESK_ORIGINAL_FILENAME "CrossDesk.exe"
#endif
#ifndef CROSSDESK_FILE_TYPE
#define CROSSDESK_FILE_TYPE VFT_APP
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION CROSSDESK_VERSION_NUMERIC
PRODUCTVERSION CROSSDESK_VERSION_NUMERIC
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef CROSSDESK_DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE CROSSDESK_FILE_TYPE
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "CrossDesk\0"
VALUE "FileDescription", CROSSDESK_FILE_DESCRIPTION "\0"
VALUE "FileVersion", CROSSDESK_VERSION_STRING "\0"
VALUE "InternalName", CROSSDESK_ORIGINAL_FILENAME "\0"
VALUE "LegalCopyright", "Copyright (C) CrossDesk contributors\0"
VALUE "OriginalFilename", CROSSDESK_ORIGINAL_FILENAME "\0"
VALUE "ProductName", "CrossDesk\0"
VALUE "ProductVersion", CROSSDESK_VERSION_STRING "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1200
END
END
+5
View File
@@ -0,0 +1,5 @@
#define CROSSDESK_FILE_DESCRIPTION "CrossDesk Windows Graphics Capture Plugin"
#define CROSSDESK_ORIGINAL_FILENAME "wgc_plugin.dll"
#define CROSSDESK_FILE_TYPE VFT_DLL
#include "version_info.rcinc"
+31
View File
@@ -84,6 +84,14 @@ int main() {
const std::string rc = ReadFile(repo_root / "scripts/windows/crossdesk.rc");
const std::string portable_rc =
ReadFile(repo_root / "scripts/windows/crossdesk_portable.rc");
const std::string service_rc =
ReadFile(repo_root / "scripts/windows/crossdesk_service.rc");
const std::string session_helper_rc =
ReadFile(repo_root / "scripts/windows/crossdesk_session_helper.rc");
const std::string wgc_plugin_rc =
ReadFile(repo_root / "scripts/windows/wgc_plugin.rc");
const std::string version_info =
ReadFile(repo_root / "scripts/windows/version_info.rcinc");
const std::string manifest =
ReadFile(repo_root / "scripts/windows/crossdesk.manifest");
const std::string debug_manifest =
@@ -100,8 +108,31 @@ int main() {
ok &= ExpectContains("crossdesk_portable.rc", portable_rc,
"crossdesk_portable.manifest");
ok &= ExpectContains("crossdesk_portable.rc", portable_rc, "RT_MANIFEST");
ok &= ExpectContains("crossdesk.rc", rc, "version_info.rcinc");
ok &= ExpectContains("crossdesk_portable.rc", portable_rc,
"version_info.rcinc");
ok &= ExpectContains("crossdesk_service.rc", service_rc,
"crossdesk_service.exe");
ok &= ExpectContains("crossdesk_session_helper.rc", session_helper_rc,
"crossdesk_session_helper.exe");
ok &= ExpectContains("crossdesk_session_helper.rc", session_helper_rc,
"CROSSDESK_PORTABLE");
ok &= ExpectContains("crossdesk_session_helper.rc", session_helper_rc,
"crossdesk_portable.manifest");
ok &= ExpectContains("wgc_plugin.rc", wgc_plugin_rc, "wgc_plugin.dll");
ok &= ExpectContains("version_info.rcinc", version_info, "ProductName");
ok &= ExpectContains("version_info.rcinc", version_info,
"ProductVersion");
ok &= ExpectContains("version_info.rcinc", version_info,
"OriginalFilename");
ok &= ExpectContains("xmake/targets.lua", targets,
"scripts/windows/crossdesk_portable.rc");
ok &= ExpectContains("xmake/targets.lua", targets,
"scripts/windows/crossdesk_service.rc");
ok &= ExpectContains("xmake/targets.lua", targets,
"scripts/windows/crossdesk_session_helper.rc");
ok &= ExpectContains("xmake/targets.lua", targets,
"scripts/windows/wgc_plugin.rc");
ok &= ExpectContains("xmake/targets.lua", targets, "CROSSDESK_PORTABLE");
ok &= ExpectContains("crossdesk.manifest", manifest,
"level=\"requireAdministrator\"");
+22
View File
@@ -35,6 +35,28 @@ function setup_options_and_dependencies()
set_languages("c++17")
set_encodings("utf-8")
local crossdesk_version = get_config("CROSSDESK_VERSION") or "0.0.0"
local version_base = crossdesk_version:gsub("^v", ""):match("^(%d[%d%.]*)") or "0.0.0"
local version_parts = {}
for part in version_base:gmatch("%d+") do
local value = tonumber(part) or 0
if value > 65535 then
value = 0
end
table.insert(version_parts, value)
if #version_parts == 4 then
break
end
end
while #version_parts < 4 do
table.insert(version_parts, 0)
end
add_defines("CROSSDESK_VERSION_STRING=\"" .. crossdesk_version .. "\"")
if is_os("windows") then
add_defines("CROSSDESK_VERSION_NUMERIC=" .. table.concat(version_parts, ","))
end
-- set_policy("build.warning", true)
-- set_warnings("all", "extra")
-- add_cxxflags("/W4", "/WX")
+3 -1
View File
@@ -297,6 +297,7 @@ function setup_targets()
add_files("src/screen_capturer/windows/screen_capturer_wgc.cpp",
"src/screen_capturer/windows/wgc_session_impl.cpp",
"src/screen_capturer/windows/wgc_plugin_entry.cpp")
add_files("scripts/windows/wgc_plugin.rc")
add_includedirs("src/common", "src/screen_capturer",
"src/screen_capturer/windows")
@@ -306,6 +307,7 @@ function setup_targets()
add_links("Advapi32", "Wtsapi32", "Ole32", "Userenv")
add_files("src/service/windows/main.cpp",
"src/service/windows/service_host.cpp")
add_files("scripts/windows/crossdesk_service.rc")
add_includedirs("src/service/windows", {public = true})
target("crossdesk_session_helper")
@@ -314,7 +316,7 @@ function setup_targets()
add_deps("rd_log", "path_manager")
add_links("Advapi32", "User32", "Wtsapi32", "Gdi32")
add_files("src/service/windows/session_helper_main.cpp")
add_files(crossdesk_windows_resource)
add_files("scripts/windows/crossdesk_session_helper.rc")
add_includedirs("src/common", "src/service/windows", {public = true})
end