Skip to content

Commit 3f08f63

Browse files
committed
CM-53930: fix onedir signing issues on mac
1 parent 457022c commit 3f08f63

2 files changed

Lines changed: 33 additions & 4 deletions

File tree

.github/workflows/build_executable.yml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,35 @@ jobs:
176176
177177
# we can't staple the app because it's executable
178178
179+
- name: Verify macOS code signatures
180+
if: runner.os == 'macOS'
181+
run: |
182+
# verify all Mach-O binaries in the output are properly signed
183+
FAILED=false
184+
while IFS= read -r file; do
185+
if file -b "$file" | grep -q "Mach-O"; then
186+
if ! codesign --verify --strict "$file" 2>/dev/null; then
187+
echo "INVALID signature: $file"
188+
codesign -dv "$file" 2>&1 || true
189+
FAILED=true
190+
fi
191+
fi
192+
done < <(find dist/cycode-cli -type f)
193+
194+
if [ "$FAILED" = true ]; then
195+
echo "Found binaries with invalid signatures!"
196+
exit 1
197+
fi
198+
199+
# verify main executable signature in detail
200+
codesign -dv --verbose=4 $PATH_TO_CYCODE_CLI_EXECUTABLE
201+
179202
- name: Test macOS signed executable
180203
if: runner.os == 'macOS'
181204
run: |
182205
file -b $PATH_TO_CYCODE_CLI_EXECUTABLE
183206
time $PATH_TO_CYCODE_CLI_EXECUTABLE version
184207
185-
# verify signature
186-
codesign -dv --verbose=4 $PATH_TO_CYCODE_CLI_EXECUTABLE
187-
188208
- name: Import cert for Windows and setup envs
189209
if: runner.os == 'Windows'
190210
env:

process_executable_file.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import os
1414
import platform
1515
import shutil
16+
import subprocess
1617
from pathlib import Path
1718
from string import Template
1819
from typing import Union
@@ -140,6 +141,14 @@ def get_cli_archive_path(output_path: Path, is_onedir: bool) -> str:
140141
return os.path.join(output_path, get_cli_archive_filename(is_onedir))
141142

142143

144+
def archive_directory(input_path: Path, output_path: str) -> None:
145+
if get_os_name() == 'darwin':
146+
# use ditto on macOS to preserve code signature metadata
147+
subprocess.run(['ditto', '-c', '-k', str(input_path), output_path], check=True)
148+
else:
149+
shutil.make_archive(output_path.removesuffix(f'.{_ARCHIVE_FORMAT}'), _ARCHIVE_FORMAT, input_path)
150+
151+
143152
def process_executable_file(input_path: Path, is_onedir: bool) -> str:
144153
output_path = input_path.parent
145154
hash_file_path = get_cli_hash_path(output_path, is_onedir)
@@ -150,7 +159,7 @@ def process_executable_file(input_path: Path, is_onedir: bool) -> str:
150159
write_hashes_db_to_file(normalized_hashes, hash_file_path)
151160

152161
archived_file_path = get_cli_archive_path(output_path, is_onedir)
153-
shutil.make_archive(archived_file_path, _ARCHIVE_FORMAT, input_path)
162+
archive_directory(input_path, f'{archived_file_path}.{_ARCHIVE_FORMAT}')
154163
shutil.rmtree(input_path)
155164
else:
156165
file_hash = get_hash_of_file(input_path)

0 commit comments

Comments
 (0)