fix(desktop): restore Windows canary builds (#2017)

This commit is contained in:
Hampus authored and GitHub committed 2026-08-25 23:54:33 +02:00
1 parent 28184f8d4d
commit da3922586a
1 file changed
+97 -30
+97 -30
View File
@@ -897,10 +897,32 @@ fn apt_get(args: &[&str]) -> Result<()> {
} }
fn install_msvc_arm64_tools_step() -> Result<()> { fn install_msvc_arm64_tools_step() -> Result<()> {
let installer = let program_files_x86 = env::var_os("ProgramFiles(x86)")
Path::new(r"C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe"); .map(PathBuf::from)
let install_path = Path::new(r"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools"); .ok_or_else(|| anyhow!("ProgramFiles(x86) is not set on the Windows runner"))?;
run_command(CommandSpec::new(installer).args([ let installer_dir = program_files_x86
.join("Microsoft Visual Studio")
.join("Installer");
let installer = installer_dir.join("setup.exe");
let vswhere = installer_dir.join("vswhere.exe");
ensure!(
vswhere.is_file(),
"Visual Studio locator not found: {}",
vswhere.display()
);
let install_path = resolve_visual_studio_install_path(&vswhere)?;
if let Some(linker) = find_msvc_arm64_linker(&install_path)? {
println!("ARM64 cross link.exe: {}", linker.display());
return Ok(());
}
ensure!(
installer.is_file(),
"Visual Studio installer not found: {}",
installer.display()
);
run_command(CommandSpec::new(&installer).args([
"modify", "modify",
"--installPath", "--installPath",
install_path.to_string_lossy().as_ref(), install_path.to_string_lossy().as_ref(),
@@ -924,9 +946,51 @@ fn install_msvc_arm64_tools_step() -> Result<()> {
"VS installer did not finish within the timeout." "VS installer did not finish within the timeout."
); );
let mut found = false; let linker = find_msvc_arm64_linker(&install_path)?.ok_or_else(|| {
anyhow!(
"ARM64 cross-build tools were not installed under {}\\VC\\Tools\\MSVC\\*\\bin\\HostX64\\arm64",
install_path.display()
)
})?;
println!("ARM64 cross link.exe: {}", linker.display());
Ok(())
}
fn resolve_visual_studio_install_path(vswhere: &Path) -> Result<PathBuf> {
let output = output_text(CommandSpec::new(vswhere).args([
"-products",
"*",
"-latest",
"-prerelease",
"-property",
"installationPath",
]))?;
let paths = output
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.collect::<Vec<_>>();
ensure!(
paths.len() == 1,
"vswhere returned {} Visual Studio installation paths; expected exactly one",
paths.len()
);
let install_path = PathBuf::from(paths[0]);
ensure!(
install_path.is_dir(),
"vswhere returned a missing Visual Studio installation: {}",
install_path.display()
);
println!("Visual Studio installation: {}", install_path.display());
Ok(install_path)
}
fn find_msvc_arm64_linker(install_path: &Path) -> Result<Option<PathBuf>> {
let msvc_root = install_path.join("VC").join("Tools").join("MSVC"); let msvc_root = install_path.join("VC").join("Tools").join("MSVC");
if msvc_root.exists() { if !msvc_root.is_dir() {
return Ok(None);
}
let mut linkers = Vec::new();
for entry in fs::read_dir(&msvc_root) for entry in fs::read_dir(&msvc_root)
.with_context(|| format!("Failed to read {}", msvc_root.display()))? .with_context(|| format!("Failed to read {}", msvc_root.display()))?
{ {
@@ -936,18 +1000,12 @@ fn install_msvc_arm64_tools_step() -> Result<()> {
.join("HostX64") .join("HostX64")
.join("arm64") .join("arm64")
.join("link.exe"); .join("link.exe");
if candidate.exists() { if candidate.is_file() {
println!("ARM64 cross link.exe: {}", candidate.display()); linkers.push(candidate);
found = true;
} }
} }
} linkers.sort();
ensure!( Ok(linkers.pop())
found,
"ARM64 cross-build tools were not installed under {}\\*\\bin\\HostX64\\arm64.",
msvc_root.display()
);
Ok(())
} }
fn windows_installer_process_running() -> Result<bool> { fn windows_installer_process_running() -> Result<bool> {
@@ -1823,7 +1881,16 @@ fn create_portable_zip_windows_step() -> Result<()> {
} }
const FLUXER_WINDOWS_SIGNER_COMMON_NAME: &str = "Fluxer Platform AB"; const FLUXER_WINDOWS_SIGNER_COMMON_NAME: &str = "Fluxer Platform AB";
const THIRD_PARTY_PUBLISHER_ALLOWLIST: &[&str] = &[]; const THIRD_PARTY_WINDOWS_SIGNATURE_ALLOWLIST: &[(&str, &str)] = &[
(
"d3dcompiler_47.dll",
"CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
),
(
"dxil.dll",
"CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
),
];
const KNOWN_OPTIONAL_WINDOWS_PE_INVENTORY: &[&str] = &["fluxer-vulkan-layer.win32-ia32-msvc.dll"]; const KNOWN_OPTIONAL_WINDOWS_PE_INVENTORY: &[&str] = &["fluxer-vulkan-layer.win32-ia32-msvc.dll"];
const WINDOWS_NATIVE_ADDON_STEMS: &[&str] = &[ const WINDOWS_NATIVE_ADDON_STEMS: &[&str] = &[
"hardware-encoder", "hardware-encoder",
@@ -2144,7 +2211,7 @@ fn assert_fluxer_signed(row: &SignatureRow) -> Result<()> {
Ok(()) Ok(())
} }
fn assert_third_party_signed(row: &SignatureRow) -> Result<()> { fn assert_third_party_signed(row: &SignatureRow, relative: &str) -> Result<()> {
ensure!( ensure!(
row.status == "Valid", row.status == "Valid",
"Authenticode status is {} (expected Valid)", "Authenticode status is {} (expected Valid)",
@@ -2154,11 +2221,13 @@ fn assert_third_party_signed(row: &SignatureRow) -> Result<()> {
.subject .subject
.as_deref() .as_deref()
.ok_or_else(|| anyhow!("Authenticode signature has no signer certificate subject"))?; .ok_or_else(|| anyhow!("Authenticode signature has no signer certificate subject"))?;
let common_name = certificate_common_name(subject)
.ok_or_else(|| anyhow!("Signer subject has no CN= component: {subject}"))?;
ensure!( ensure!(
THIRD_PARTY_PUBLISHER_ALLOWLIST.contains(&common_name), THIRD_PARTY_WINDOWS_SIGNATURE_ALLOWLIST
"Signer CN '{common_name}' is not an allowlisted third-party publisher" .iter()
.any(|(allowed_path, allowed_subject)| {
relative.eq_ignore_ascii_case(allowed_path) && subject == *allowed_subject
}),
"Signer subject '{subject}' is not allowlisted for {relative}"
); );
ensure!( ensure!(
row.ts_subject.is_some(), row.ts_subject.is_some(),
@@ -2167,10 +2236,10 @@ fn assert_third_party_signed(row: &SignatureRow) -> Result<()> {
Ok(()) Ok(())
} }
fn assert_signed_by_known_publisher(row: &SignatureRow) -> Result<()> { fn assert_signed_by_known_publisher(row: &SignatureRow, relative: &str) -> Result<()> {
match assert_fluxer_signed(row) { match assert_fluxer_signed(row) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
Err(fluxer_error) => assert_third_party_signed(row) Err(fluxer_error) => assert_third_party_signed(row, relative)
.map_err(|third_party_error| anyhow!("{fluxer_error}; {third_party_error}")), .map_err(|third_party_error| anyhow!("{fluxer_error}; {third_party_error}")),
} }
} }
@@ -2333,22 +2402,20 @@ fn verify_windows_pe_signatures(
)); ));
continue; continue;
}; };
if let Err(error) = assert_signed_by_known_publisher(row) { if let Err(error) = assert_signed_by_known_publisher(row, &relative) {
failures.push(format!("{relative}: {error}")); failures.push(format!("{relative}: {error}"));
} }
} }
ensure!( ensure!(
failures.is_empty(), failures.is_empty(),
"{label}: {} of {} Windows binaries are not signed by '{}':\n{}", "{label}: {} of {} Windows binaries do not have an approved signature:\n{}",
failures.len(), failures.len(),
files.len(), files.len(),
FLUXER_WINDOWS_SIGNER_COMMON_NAME,
failures.join("\n") failures.join("\n")
); );
println!( println!(
"{label}: verified {} Windows binaries signed by '{}'.", "{label}: verified {} Windows binary signatures.",
files.len(), files.len()
FLUXER_WINDOWS_SIGNER_COMMON_NAME
); );
Ok(()) Ok(())
} }