Test build of analytics

This commit is contained in:
Mykola Grymalyuk
2023-04-11 13:28:33 -06:00
parent 62f619da99
commit 52211def51
5 changed files with 175 additions and 2 deletions

View File

@@ -18,10 +18,12 @@ jobs:
commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }} commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }}
MAC_NOTARIZATION_USERNAME: ${{ secrets.MAC_NOTARIZATION_USERNAME }} MAC_NOTARIZATION_USERNAME: ${{ secrets.MAC_NOTARIZATION_USERNAME }}
MAC_NOTARIZATION_PASSWORD: ${{ secrets.MAC_NOTARIZATION_PASSWORD }} MAC_NOTARIZATION_PASSWORD: ${{ secrets.MAC_NOTARIZATION_PASSWORD }}
ANALYTICS_KEY: ${{ secrets.ANALYTICS_KEY }}
ANALYTICS_SITE: ${{ secrets.ANALYTICS_SITE }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- run: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 Build-Binary.command --reset_binaries --branch "${{ env.branch }}" --commit "${{ env.commiturl }}" --commit_date "${{ env.commitdate }}" - run: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 Build-Binary.command --reset_binaries --branch "${{ env.branch }}" --commit "${{ env.commiturl }}" --commit_date "${{ env.commitdate }}" --key "${{ env.ANALYTICS_KEY }}" --site "${{ env.ANALYTICS_SITE }}"
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' - run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
- run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip - run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip
- run: xcrun altool --notarize-app --primary-bundle-id "com.dortania.opencore-legacy-patcher" --username "${{ env.MAC_NOTARIZATION_USERNAME }}" --password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --file OpenCore-Patcher-wxPython.app.zip - run: xcrun altool --notarize-app --primary-bundle-id "com.dortania.opencore-legacy-patcher" --username "${{ env.MAC_NOTARIZATION_USERNAME }}" --password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --file OpenCore-Patcher-wxPython.app.zip

View File

@@ -61,6 +61,8 @@ class CreateBinary:
parser.add_argument('--commit', type=str, help='Git commit URL') parser.add_argument('--commit', type=str, help='Git commit URL')
parser.add_argument('--commit_date', type=str, help='Git commit date') parser.add_argument('--commit_date', type=str, help='Git commit date')
parser.add_argument('--reset_binaries', action='store_true', help='Force redownload and imaging of payloads') parser.add_argument('--reset_binaries', action='store_true', help='Force redownload and imaging of payloads')
parser.add_argument('--key', type=str, help='Developer key for signing')
parser.add_argument('--site', type=str, help='Path to server')
args = parser.parse_args() args = parser.parse_args()
return args return args
@@ -132,17 +134,85 @@ class CreateBinary:
print(rm_output.stderr.decode('utf-8')) print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed") raise Exception("Remove failed")
self._embed_key()
print("- Building GUI binary...") print("- Building GUI binary...")
build_args = [self.pyinstaller_path, "./OpenCore-Patcher-GUI.spec", "--noconfirm"] build_args = [self.pyinstaller_path, "./OpenCore-Patcher-GUI.spec", "--noconfirm"]
build_result = subprocess.run(build_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) build_result = subprocess.run(build_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self._strip_key()
if build_result.returncode != 0: if build_result.returncode != 0:
print("- Build failed") print("- Build failed")
print(build_result.stderr.decode('utf-8')) print(build_result.stderr.decode('utf-8'))
raise Exception("Build failed") raise Exception("Build failed")
def _embed_key(self):
"""
Embed developer key into binary
"""
if not self.args.key:
print("- No developer key provided, skipping...")
return
if not self.args.site:
print("- No site provided, skipping...")
return
print("- Embedding developer key...")
if not Path("./resources/analytics_handler.py").exists():
print("- analytics_handler.py not found")
return
lines = []
with open("./resources/analytics_handler.py", "r") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("SITE_KEY: str = "):
lines[i] = f"SITE_KEY: str = \"{self.args.key}\"\n"
elif line.startswith("ANALYTICS_SERVER: str = "):
lines[i] = f"ANALYTICS_SERVER: str = \"{self.args.site}\"\n"
with open("./resources/analytics_handler.py", "w") as f:
f.writelines(lines)
def _strip_key(self):
"""
Strip developer key from binary
"""
if not self.args.key:
print("- No developer key provided, skipping...")
return
if not self.args.site:
print("- No site provided, skipping...")
return
print("- Stripping developer key...")
if not Path("./resources/analytics_handler.py").exists():
print("- analytics_handler.py not found")
return
lines = []
with open("./resources/analytics_handler.py", "r") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("SITE_KEY: str = "):
lines[i] = f"SITE_KEY: str = \"\"\n"
elif line.startswith("ANALYTICS_SERVER: str = "):
lines[i] = f"ANALYTICS_SERVER: str = \"\"\n"
with open("./resources/analytics_handler.py", "w") as f:
f.writelines(lines)
def _delete_extra_binaries(self): def _delete_extra_binaries(self):
""" """
Delete extra binaries from payloads directory Delete extra binaries from payloads directory

View File

@@ -0,0 +1,94 @@
import datetime
import plistlib
from pathlib import Path
import json
from resources import network_handler, constants
DATE_FORMAT: str = "%Y-%m-%d %H-%M-%S"
ANALYTICS_SERVER: str = ""
SITE_KEY: str = ""
VALID_ENTRIES: dict = {
'KEY': str, # Prevent abuse (embedded at compile time)
'UNIQUE_IDENTITY': str, # Host's UUID as SHA1 hash
'APPLICATION_NAME': str, # ex. OpenCore Legacy Patcher
'APPLICATION_VERSION': str, # ex. 0.2.0
'OS_VERSION': str, # ex. 10.15.7
'MODEL': str, # ex. MacBookPro11,5
'GPUS': list, # ex. ['Intel Iris Pro', 'AMD Radeon R9 M370X']
'FIRMWARE': str, # ex. APPLE
'LOCATION': str, # ex. 'US' (just broad region, don't need to be specific)
'TIMESTAMP': datetime.datetime, # ex. 2021-09-01-12-00-00
}
class Analytics:
def __init__(self, global_constants: constants.Constants) -> None:
self.constants: constants.Constants = global_constants
self._generate_base_data()
self._post_data()
def _get_country(self) -> str:
# Get approximate country from .GlobalPreferences.plist
path = "/Library/Preferences/.GlobalPreferences.plist"
if not Path(path).exists():
return "US"
try:
result = plistlib.load(Path(path).open("rb"))
except:
return "US"
if "Country" not in result:
return "US"
return result["Country"]
def _generate_base_data(self) -> None:
self.unique_identity = str(self.constants.computer.uuid_sha1)
self.application = str("OpenCore Legacy Patcher")
self.version = str(self.constants.patcher_version)
self.os = str( self.constants.detected_os_version)
self.model = str(self.constants.computer.real_model)
self.gpus = []
self.firmware = str(self.constants.computer.firmware_vendor)
self.location = str(self._get_country())
for gpu in self.constants.computer.gpus:
self.gpus.append(str(gpu.arch))
self.data = {
'KEY': SITE_KEY,
'UNIQUE_IDENTITY': self.unique_identity,
'APPLICATION_NAME': self.application,
'APPLICATION_VERSION': self.version,
'OS_VERSION': self.os,
'MODEL': self.model,
'GPUS': self.gpus,
'FIRMWARE': self.firmware,
'LOCATION': self.location,
'TIMESTAMP': str(datetime.datetime.now().strftime(DATE_FORMAT)),
}
# convert to JSON:
self.data = json.dumps(self.data)
def _post_data(self) -> None:
# Post data to analytics server
if ANALYTICS_SERVER == "":
return
if SITE_KEY == "":
return
network_handler.NetworkUtilities().post(ANALYTICS_SERVER, json = self.data)

View File

@@ -6,6 +6,7 @@ import enum
import itertools import itertools
import subprocess import subprocess
import plistlib import plistlib
import hashlib
from pathlib import Path from pathlib import Path
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, ClassVar, Optional, Type, Union from typing import Any, ClassVar, Optional, Type, Union
@@ -491,6 +492,7 @@ class Computer:
reported_model: Optional[str] = None reported_model: Optional[str] = None
reported_board_id: Optional[str] = None reported_board_id: Optional[str] = None
build_model: Optional[str] = None build_model: Optional[str] = None
uuid_sha1: Optional[str] = None
gpus: list[GPU] = field(default_factory=list) gpus: list[GPU] = field(default_factory=list)
igpu: Optional[GPU] = None # Shortcut for IGPU igpu: Optional[GPU] = None # Shortcut for IGPU
dgpu: Optional[GPU] = None # Shortcut for GFX0 dgpu: Optional[GPU] = None # Shortcut for GFX0
@@ -719,6 +721,8 @@ class Computer:
else: else:
board = "board-id" board = "board-id"
self.reported_board_id = ioreg.corefoundation_to_native(ioreg.IORegistryEntryCreateCFProperty(entry, board, ioreg.kCFAllocatorDefault, ioreg.kNilOptions)).strip(b"\0").decode() # type: ignore self.reported_board_id = ioreg.corefoundation_to_native(ioreg.IORegistryEntryCreateCFProperty(entry, board, ioreg.kCFAllocatorDefault, ioreg.kNilOptions)).strip(b"\0").decode() # type: ignore
self.uuid_sha1 = ioreg.corefoundation_to_native(ioreg.IORegistryEntryCreateCFProperty(entry, "IOPlatformUUID", ioreg.kCFAllocatorDefault, ioreg.kNilOptions)) # type: ignore
self.uuid_sha1 = hashlib.sha1(self.uuid_sha1.encode()).hexdigest()
ioreg.IOObjectRelease(entry) ioreg.IOObjectRelease(entry)
# Real model # Real model

View File

@@ -16,7 +16,8 @@ from resources import (
arguments, arguments,
reroute_payloads, reroute_payloads,
commit_info, commit_info,
logging_handler logging_handler,
analytics_handler,
) )
@@ -110,4 +111,6 @@ class OpenCoreLegacyPatcher:
while self.constants.unpack_thread.is_alive(): while self.constants.unpack_thread.is_alive():
time.sleep(0.1) time.sleep(0.1)
threading.Thread(target=analytics_handler.Analytics, args=(self.constants,)).start()
arguments.arguments(self.constants) arguments.arguments(self.constants)