Skip to content

Commit 0011cc3

Browse files
committed
feat(build): add digital signatures for windows build
1 parent a271283 commit 0011cc3

File tree

1 file changed

+45
-6
lines changed

1 file changed

+45
-6
lines changed

scripts/createmsi.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
"""
33
This script is for generating MSI packages
44
for Windows users.
5+
6+
To generate a self-signed certificate for code signing:
7+
8+
openssl genrsa -out code-signing.key 2048
9+
openssl req -new -key code-signing.key -out code-signing.csr
10+
openssl x509 -req -days 365 -in code-signing.csr -signkey code-signing.key -out code-signing.crt
11+
openssl pkcs12 -export -out code-signing.pfx -inkey code-signing.key -in code-signing.crt -name "ABCodeSigningCert"
512
"""
13+
import logging
614
import os
715
import shutil
816
import subprocess
@@ -13,8 +21,11 @@
1321

1422
sys.path.append(os.getcwd())
1523

24+
# sometimes the signing tool exe is not on PATH, so allow user to set env to it
25+
WINDOWS_SDK_BIN = os.environ.get("WINDOWS_SDK_BIN", "")
1626
# Elementtree does not support CDATA. So hack it.
1727
WINVER_CHECK = "Installed OR (VersionNT64 > 602)>"
28+
logger = logging.getLogger(__name__)
1829

1930

2031
def gen_guid():
@@ -55,17 +66,17 @@ class PackageGenerator:
5566
Package generator for MSI packages
5667
"""
5768

58-
def __init__(self):
69+
def __init__(self, signing_certificate=None, version=None):
5970
self.product_name = "Activity Browser"
6071
self.manufacturer = "The Activity Browser Team"
61-
self.version = os.environ.get("VERSION", "0.0.0")
72+
self.version = version or os.environ.get("VERSION", "0.0.0")
6273
if "-" in self.version:
63-
versions = self.version.split("-")
74+
versions = self.version.split("-")
6475
self.version = "{}.{}".format(versions[0], versions[1])
6576
print("Using version {} instead".format(self.version))
6677
self.root = None
6778
self.guid = "*"
68-
self.update_guid = "141527EE-E28A-4D14-97A4-92E6075D28B2"
79+
self.update_guid = "728A617A-4F3F-49BB-B9E5-5D02F037B67B"
6980
self.main_xml = "activitybrowser.wxs"
7081
self.main_o = "activitybrowser.wixobj"
7182
self.final_output = "activitybrowser-{}-64.msi".format(self.version)
@@ -100,6 +111,7 @@ def __init__(self):
100111
self.feature_components = {}
101112
for s_d in self.staging_dirs:
102113
self.feature_components[s_d] = []
114+
self.signing_certificate = signing_certificate
103115

104116
def build_dist(self):
105117
"""
@@ -121,7 +133,7 @@ def build_dist(self):
121133
pyinst_cmd = [
122134
pyinstaller,
123135
"activity-browser.spec",
124-
# "--clean",
136+
"--clean",
125137
"--distpath",
126138
pyinstaller_tmpdir,
127139
]
@@ -131,6 +143,25 @@ def build_dist(self):
131143
if not os.path.exists(os.path.join(main_stage, "activity-browser.exe")):
132144
sys.exit("activity-browser exe missing from staging dir.")
133145

146+
self.sign_files(os.path.join(main_stage, "*.exe"))
147+
148+
def sign_files(self, pattern: str):
149+
if self.signing_certificate is None:
150+
return
151+
for file in glob(pattern):
152+
logger.info("Signing file: %s", file)
153+
subprocess.check_call([
154+
os.path.join(WINDOWS_SDK_BIN, 'signtool'),
155+
'sign',
156+
'/fd',
157+
'SHA256',
158+
'/t',
159+
'http://timestamp.digicert.com',
160+
'/f',
161+
self.signing_certificate,
162+
file
163+
])
164+
134165
def del_infodirs(self, dirname):
135166
# Starting with 3.9.something there are some
136167
# extra metadatadirs that have a hyphen in their
@@ -452,6 +483,7 @@ def build_package(self):
452483
self.main_xml,
453484
]
454485
)
486+
self.sign_files("*.msi")
455487

456488

457489
def install_wix():
@@ -475,14 +507,21 @@ def install_wix():
475507

476508

477509
if __name__ == "__main__":
510+
import argparse
511+
512+
parser = argparse.ArgumentParser()
513+
parser.add_argument("--signing-certificate", help="local signing certificate (pfx format)")
514+
parser.add_argument("--version", help="version that the msi will be")
515+
options = parser.parse_args()
516+
478517
if not os.path.exists("activity-browser.spec"):
479518
sys.exit(print("Run me in the top level source dir."))
480519
if not shutil.which("wix"):
481520
install_wix()
482521
if not shutil.which("pyinstaller"):
483522
subprocess.check_call(["pip", "install", "--upgrade", "pyinstaller"])
484523

485-
p = PackageGenerator()
524+
p = PackageGenerator(**options.__dict__)
486525
p.build_dist()
487526
p.generate_files()
488527
p.build_package()

0 commit comments

Comments
 (0)