205 lines
6.8 KiB
Python
205 lines
6.8 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# SPDX-FileCopyrightText: 2011-2024 Blender Authors
|
|
# <pep8 compliant>
|
|
|
|
import pathlib
|
|
import sys
|
|
|
|
from typing import Optional, Sequence
|
|
|
|
import worker.blender
|
|
import worker.utils
|
|
|
|
|
|
def sign_windows_files(
|
|
service_env_id: str,
|
|
file_paths: Sequence[pathlib.Path],
|
|
description: Optional[str] = None,
|
|
certificate_id: str = "",
|
|
) -> None:
|
|
import conf.worker
|
|
|
|
worker_config = conf.worker.get_config(service_env_id)
|
|
|
|
# TODO: Rotate them if first 1 fails
|
|
worker_config.sign_code_windows_time_servers[0]
|
|
server_url = worker_config.sign_code_windows_server_url
|
|
if not certificate_id:
|
|
certificate_id = worker_config.sign_code_windows_certificate
|
|
|
|
dry_run = False
|
|
if service_env_id == "LOCAL" and not certificate_id:
|
|
worker.utils.warning("Performing dry run on LOCAL service environment")
|
|
dry_run = True
|
|
|
|
cmd_args = [
|
|
sys.executable,
|
|
"C:\\tools\\codesign.py",
|
|
"--server-url",
|
|
worker.utils.HiddenArgument(server_url),
|
|
]
|
|
if description:
|
|
cmd_args += ["--description", description]
|
|
|
|
cmd: worker.utils.CmdSequence = cmd_args
|
|
|
|
# Signing one file at a time causes a stampede on servers, resulting in blocking.
|
|
# Instead sign in chunks of multiple files.
|
|
chunk_size = 25 # Sign how many files at a time
|
|
retry_count = 3
|
|
|
|
for i in range(0, len(file_paths), chunk_size):
|
|
file_chunks = file_paths[i : i + chunk_size]
|
|
worker.utils.call(
|
|
list(cmd) + list(file_chunks), retry_count=retry_count, dry_run=dry_run
|
|
)
|
|
|
|
|
|
def sign_windows(service_env_id: str, install_path: pathlib.Path) -> None:
|
|
# TODO: Why use a junction? Is there some failure with long file paths?
|
|
# worker.utils.info("Creating building link")
|
|
# temp_build_root_path = pathlib.Path("C:/BlenderTemp")
|
|
# os.makedirs(temp_build_root_path, exist_ok=True)
|
|
# orig_install_path = install_path
|
|
# install_path = temp_build_root_path / install_path.name
|
|
|
|
try:
|
|
# TODO
|
|
# New-Item -type Junction -path install_path -value orig_install_path
|
|
|
|
worker.utils.info("Collecting files to process")
|
|
file_paths = list(install_path.glob("*.exe"))
|
|
file_paths += list(install_path.glob("*.dll"))
|
|
file_paths += list(install_path.glob("*.pyd"))
|
|
file_paths = [f for f in file_paths if str(f).find("blender.crt") == -1]
|
|
for f in file_paths:
|
|
print(f)
|
|
|
|
sign_windows_files(service_env_id, file_paths)
|
|
finally:
|
|
# worker.utils.info(f"Removing temporary folder {temp_build_root_path}")
|
|
# worker.utils.remove_dir(temp_build_root_path, retry_count=5, retry_wait_time=5.0)
|
|
|
|
# TODO: is this really necessary?
|
|
# worker.utils.info("Flushing volume cache...")
|
|
# Write-VolumeCache -DriveLetter C
|
|
|
|
# core_shell_retry_command -retry_count 5 -delay_in_milliseconds 1000 -script_block `
|
|
# worker.utils.info("Junction information...")
|
|
# junction = Get-Item -Path install_path
|
|
# worker.utils.info(junction | Format-Table)
|
|
# worker.utils.info("Attempting to remove...")
|
|
# junction.Delete()
|
|
# worker.utils.info("Junction deleted!")
|
|
pass
|
|
|
|
worker.utils.info("End of codesign steps")
|
|
|
|
|
|
def sign_darwin_files(
|
|
builder: worker.blender.CodeBuilder,
|
|
file_paths: Sequence[pathlib.Path],
|
|
entitlements_file_name: str,
|
|
) -> None:
|
|
entitlements_path = (
|
|
builder.code_path / "release" / "darwin" / entitlements_file_name
|
|
)
|
|
|
|
if not entitlements_path.exists():
|
|
raise Exception(f"File {entitlements_path} not found, aborting")
|
|
|
|
worker_config = builder.get_worker_config()
|
|
certificate_id = worker_config.sign_code_darwin_certificate
|
|
|
|
dry_run = False
|
|
if builder.service_env_id == "LOCAL" and not certificate_id:
|
|
worker.utils.warning("Performing dry run on LOCAL service environment")
|
|
dry_run = True
|
|
|
|
keychain_password = worker_config.darwin_keychain_password(builder.service_env_id)
|
|
cmd: worker.utils.CmdSequence = [
|
|
"security",
|
|
"unlock-keychain",
|
|
"-p",
|
|
worker.utils.HiddenArgument(keychain_password),
|
|
]
|
|
worker.utils.call(cmd, dry_run=dry_run)
|
|
|
|
for file_path in file_paths:
|
|
if file_path.is_dir() and file_path.suffix != ".app":
|
|
continue
|
|
|
|
# Remove signature
|
|
if file_path.suffix != ".dmg":
|
|
worker.utils.call(
|
|
["codesign", "--remove-signature", file_path],
|
|
exit_on_error=False,
|
|
dry_run=dry_run,
|
|
)
|
|
|
|
# Add signature
|
|
worker.utils.call(
|
|
[
|
|
"codesign",
|
|
"--force",
|
|
"--timestamp",
|
|
"--options",
|
|
"runtime",
|
|
f"--entitlements={entitlements_path}",
|
|
"--sign",
|
|
certificate_id,
|
|
file_path,
|
|
],
|
|
retry_count=3,
|
|
dry_run=dry_run,
|
|
)
|
|
if file_path.suffix == ".app":
|
|
worker.utils.info(f"Vaildating app bundle {file_path}")
|
|
worker.utils.call(
|
|
["codesign", "-vvv", "--deep", "--strict", file_path], dry_run=dry_run
|
|
)
|
|
|
|
|
|
def sign_darwin(builder: worker.blender.CodeBuilder) -> None:
|
|
bundle_path = builder.install_dir / "Blender.app"
|
|
|
|
# Executables
|
|
sign_path = bundle_path / "Contents" / "MacOS"
|
|
worker.utils.info(f"Collecting files to process in {sign_path}")
|
|
sign_darwin_files(builder, list(sign_path.rglob("*")), "entitlements.plist")
|
|
|
|
# Thumbnailer app extension.
|
|
thumbnailer_appex_path = (
|
|
bundle_path / "Contents" / "PlugIns" / "blender-thumbnailer.appex"
|
|
)
|
|
if thumbnailer_appex_path.exists():
|
|
sign_path = thumbnailer_appex_path / "Contents" / "MacOS"
|
|
worker.utils.info(f"Collecting files to process in {sign_path}")
|
|
sign_darwin_files(
|
|
builder, list(sign_path.rglob("*")), "thumbnailer_entitlements.plist"
|
|
)
|
|
|
|
# Shared librarys and Python
|
|
sign_path = bundle_path / "Contents" / "Resources"
|
|
worker.utils.info(f"Collecting files to process in {sign_path}")
|
|
file_paths = list(
|
|
set(sign_path.rglob("*.dylib"))
|
|
| set(sign_path.rglob("*.so"))
|
|
| set(sign_path.rglob("python3.*"))
|
|
)
|
|
sign_darwin_files(builder, file_paths, "entitlements.plist")
|
|
|
|
# Bundle
|
|
worker.utils.info(f"Signing app bundle {bundle_path}")
|
|
sign_darwin_files(builder, [bundle_path], "entitlements.plist")
|
|
|
|
|
|
def sign(builder: worker.blender.CodeBuilder) -> None:
|
|
builder.setup_build_environment()
|
|
|
|
if builder.platform == "windows":
|
|
sign_windows(builder.service_env_id, builder.install_dir)
|
|
elif builder.platform == "darwin":
|
|
sign_darwin(builder)
|
|
else:
|
|
worker.utils.info("No code signing to be done on this platform")
|