mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2025-12-19 04:30:14 -06:00
CI: Add PKG building support
This commit is contained in:
22
.github/workflows/build-app-wxpython.yml
vendored
22
.github/workflows/build-app-wxpython.yml
vendored
@@ -27,9 +27,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build Binary
|
||||
run: /Library/Frameworks/Python.framework/Versions/3.11/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 }}"
|
||||
|
||||
# - name: Import Certificate
|
||||
# if: (!security find-certificate -c "${{ env.MAC_CODESIGN_IDENTITY }}")
|
||||
# uses: apple-actions/import-codesign-certs@v2
|
||||
@@ -37,20 +34,23 @@ jobs:
|
||||
# p12-file-base64: ${{ secrets.MAC_CODESIGN_CERT }}
|
||||
# p12-password: ${{ secrets.MAC_NOTARIZATION_PASSWORD }}
|
||||
|
||||
- name: Codesign Binary
|
||||
run: 'codesign -s "${{ env.MAC_CODESIGN_IDENTITY }}" -v --force --deep --timestamp --entitlements ./ci_tooling/entitlements/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
|
||||
- name: Install Dependencies
|
||||
run: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m pip install -r requirements.txt
|
||||
|
||||
- name: Package Binary
|
||||
run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip
|
||||
|
||||
- name: Notarize Binary
|
||||
run: xcrun notarytool submit OpenCore-Patcher-wxPython.app.zip --apple-id "${{ env.MAC_NOTARIZATION_USERNAME }}" --password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --team-id "${{ env.MAC_NOTARIZATION_TEAM_ID }}"
|
||||
- name: Build Binary
|
||||
run: >
|
||||
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3 Build-Suite.command
|
||||
--application-signing-identity "${{ env.MAC_CODESIGN_IDENTITY }}"
|
||||
--notarization-apple-id "${{ env.MAC_NOTARIZATION_USERNAME }}" --notarization-password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --notarization-team-id "${{ env.MAC_NOTARIZATION_TEAM_ID }}"
|
||||
--git-branch "${{ env.branch }}" --git-commit-url "${{ env.commiturl }}" --git-commit-date "${{ env.commitdate }}"
|
||||
--reset-dmg-cache --reset-pyinstaller-cache
|
||||
--analytics-key "${{ env.ANALYTICS_KEY }}" --analytics-endpoint "${{ env.ANALYTICS_SITE }}"
|
||||
|
||||
- name: Generate support package
|
||||
run: /usr/local/bin/packagesbuild ./ci_tooling/autopkg/AutoPkg-Assets-Setup.pkgproj
|
||||
|
||||
- name: Prepare App for Upload
|
||||
run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip
|
||||
run: /bin/mv ./dist/OpenCore-Patcher.app.zip ./OpenCore-Patcher-GUI.app.zip
|
||||
|
||||
- name: Upload App to Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
107
Build-Suite.command
Normal file
107
Build-Suite.command
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Build-Suite.command: Generate OpenCore-Patcher.app and OpenCore-Patcher.pkg
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import argparse
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from ci_tooling.build_module import (
|
||||
application,
|
||||
disk_images,
|
||||
package,
|
||||
sign_notarize
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""
|
||||
Parse Command Line Arguments
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(description="Build OpenCore Legacy Patcher Suite")
|
||||
|
||||
# Code Signing Parameters
|
||||
# - Application Signing Identity
|
||||
# - Installer Signing Identity
|
||||
parser.add_argument("--application-signing-identity", type=str, help="Application Signing Identity")
|
||||
parser.add_argument("--installer-signing-identity", type=str, help="Installer Signing Identity")
|
||||
|
||||
|
||||
# Notarization Parameters
|
||||
# - Notarization Apple ID
|
||||
# - Notarization Password
|
||||
# - Notarization Team ID
|
||||
parser.add_argument("--notarization-apple-id", type=str, help="Notarization Apple ID", default=None)
|
||||
parser.add_argument("--notarization-password", type=str, help="Notarization Password", default=None)
|
||||
parser.add_argument("--notarization-team-id", type=str, help="Notarization Team ID", default=None)
|
||||
|
||||
# GitHub Actions CI/CD Parameters
|
||||
# - Git Branch
|
||||
# - Git Commit
|
||||
# - Git Commit Date
|
||||
parser.add_argument("--git-branch", type=str, help="Git Branch", default=None)
|
||||
parser.add_argument("--git-commit-url", type=str, help="Git Commit URL", default=None)
|
||||
parser.add_argument("--git-commit-date", type=str, help="Git Commit Date", default=None)
|
||||
|
||||
# Local Build Parameters
|
||||
# - Reset payloads.dmg
|
||||
# - Clean PyInstaller Cache
|
||||
parser.add_argument("--reset-dmg-cache", action="store_true", help="Redownload PatcherSupportPkg.dmg and regenerate payloads.dmg", default=False)
|
||||
parser.add_argument("--reset-pyinstaller-cache", action="store_true", help="Clean PyInstaller Cache", default=False)
|
||||
|
||||
# Analytics Parameters
|
||||
# - Key
|
||||
# - Site
|
||||
parser.add_argument("--analytics-key", type=str, help="Analytics Key", default=None)
|
||||
parser.add_argument("--analytics-endpoint", type=str, help="Analytics Endpoint", default=None)
|
||||
|
||||
# Parse Arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
# Set 'Current Working Directory' to script directory
|
||||
os.chdir(Path(__file__).resolve().parent)
|
||||
|
||||
# Prepare workspace
|
||||
disk_images.GenerateDiskImages(args.reset_dmg_cache).generate()
|
||||
|
||||
# Build OpenCore-Patcher.app
|
||||
application.GenerateApplication(
|
||||
reset_pyinstaller_cache=args.reset_pyinstaller_cache,
|
||||
git_branch=args.git_branch,
|
||||
git_commit_url=args.git_commit_url,
|
||||
git_commit_date=args.git_commit_date,
|
||||
analytics_key=args.analytics_key,
|
||||
analytics_endpoint=args.analytics_endpoint,
|
||||
).generate()
|
||||
|
||||
# Sign OpenCore-Patcher.app
|
||||
sign_notarize.SignAndNotarize(
|
||||
path=Path("dist/OpenCore-Patcher.app"),
|
||||
signing_identity=args.application_signing_identity,
|
||||
notarization_apple_id=args.notarization_apple_id,
|
||||
notarization_password=args.notarization_password,
|
||||
notarization_team_id=args.notarization_team_id,
|
||||
entitlements=Path("./ci_tooling/entitlements/entitlements.plist"),
|
||||
).sign_and_notarize()
|
||||
|
||||
# Build OpenCore-Patcher.pkg
|
||||
package.GeneratePackage().generate()
|
||||
|
||||
# Sign OpenCore-Patcher.pkg
|
||||
sign_notarize.SignAndNotarize(
|
||||
path=Path("dist/OpenCore-Patcher.pkg"),
|
||||
signing_identity=args.installer_signing_identity,
|
||||
notarization_apple_id=args.notarization_apple_id,
|
||||
notarization_password=args.notarization_password,
|
||||
notarization_team_id=args.notarization_team_id,
|
||||
).sign_and_notarize()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
_start = time.time()
|
||||
main()
|
||||
print(f"Build script completed in {str(round(time.time() - _start, 2))} seconds")
|
||||
@@ -14,6 +14,7 @@ filesToRemove=(
|
||||
"/Library/Application Support/Dortania/Update.plist"
|
||||
"/Library/Application Support/Dortania/OpenCore-Patcher.app"
|
||||
"/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"
|
||||
"/Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
|
||||
)
|
||||
|
||||
|
||||
|
||||
176
ci_tooling/build_module/application.py
Normal file
176
ci_tooling/build_module/application.py
Normal file
@@ -0,0 +1,176 @@
|
||||
import sys
|
||||
import time
|
||||
import plistlib
|
||||
import subprocess
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from opencore_legacy_patcher import constants
|
||||
from opencore_legacy_patcher.support import subprocess_wrapper
|
||||
|
||||
|
||||
class GenerateApplication:
|
||||
"""
|
||||
Generate OpenCore-Patcher.app
|
||||
"""
|
||||
|
||||
def __init__(self, reset_pyinstaller_cache: bool = False, git_branch: str = None, git_commit_url: str = None, git_commit_date: str = None, analytics_key: str = None, analytics_endpoint: str = None) -> None:
|
||||
"""
|
||||
Initialize
|
||||
"""
|
||||
self._pyinstaller = [sys.executable, "-m", "PyInstaller"]
|
||||
self._application_output = Path("./dist/OpenCore-Patcher.app")
|
||||
|
||||
self._reset_pyinstaller_cache = reset_pyinstaller_cache
|
||||
|
||||
self._git_branch = git_branch
|
||||
self._git_commit_url = git_commit_url
|
||||
self._git_commit_date = git_commit_date
|
||||
|
||||
self._analytics_key = analytics_key
|
||||
self._analytics_endpoint = analytics_endpoint
|
||||
|
||||
|
||||
def _generate_application(self) -> None:
|
||||
"""
|
||||
Generate PyInstaller Application
|
||||
"""
|
||||
if self._application_output.exists():
|
||||
subprocess_wrapper.run_and_verify(["/bin/rm", "-rf", self._application_output], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
print("Generating OpenCore-Patcher.app")
|
||||
_args = self._pyinstaller + ["./OpenCore-Patcher-GUI.spec", "--noconfirm"]
|
||||
if self._reset_pyinstaller_cache:
|
||||
_args.append("--clean")
|
||||
|
||||
subprocess_wrapper.run_and_verify(_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
|
||||
def _embed_analytics_key(self) -> None:
|
||||
"""
|
||||
Embed analytics key
|
||||
"""
|
||||
_file = Path("./opencore_legacy_patcher/support/analytics_handler.py")
|
||||
|
||||
if not all([self._analytics_key, self._analytics_endpoint]):
|
||||
print("Analytics key or endpoint not provided, skipping embedding")
|
||||
return
|
||||
|
||||
print("Embedding analytics data")
|
||||
if not Path(_file).exists():
|
||||
raise FileNotFoundError("analytics_handler.py not found")
|
||||
|
||||
lines = []
|
||||
with open(_file, "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._analytics_key}\"\n"
|
||||
elif line.startswith("ANALYTICS_SERVER: str = "):
|
||||
lines[i] = f"ANALYTICS_SERVER: str = \"{self._analytics_endpoint}\"\n"
|
||||
|
||||
with open(_file, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def _remove_analytics_key(self) -> None:
|
||||
"""
|
||||
Remove analytics key
|
||||
"""
|
||||
_file = Path("./opencore_legacy_patcher/support/analytics_handler.py")
|
||||
|
||||
if not all([self._analytics_key, self._analytics_endpoint]):
|
||||
return
|
||||
|
||||
print("Removing analytics data")
|
||||
if not _file.exists():
|
||||
raise FileNotFoundError("analytics_handler.py not found")
|
||||
|
||||
lines = []
|
||||
with open(_file, "r") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith("SITE_KEY: str = "):
|
||||
lines[i] = "SITE_KEY: str = \"\"\n"
|
||||
elif line.startswith("ANALYTICS_SERVER: str = "):
|
||||
lines[i] = "ANALYTICS_SERVER: str = \"\"\n"
|
||||
|
||||
with open(_file, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def _patch_load_command(self):
|
||||
"""
|
||||
Patch LC_VERSION_MIN_MACOSX in Load Command to report 10.10
|
||||
|
||||
By default Pyinstaller will create binaries supporting 10.13+
|
||||
However this limitation is entirely arbitrary for our libraries
|
||||
and instead we're able to support 10.10 without issues.
|
||||
|
||||
To verify set version:
|
||||
otool -l ./dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher
|
||||
|
||||
cmd LC_VERSION_MIN_MACOSX
|
||||
cmdsize 16
|
||||
version 10.13
|
||||
sdk 10.9
|
||||
"""
|
||||
_file = self._application_output / "Contents" / "MacOS" / "OpenCore-Patcher"
|
||||
|
||||
_find = b'\x00\x0D\x0A\x00' # 10.13 (0xA0D)
|
||||
_replace = b'\x00\x0A\x0A\x00' # 10.10 (0xA0A)
|
||||
|
||||
print("Patching LC_VERSION_MIN_MACOSX")
|
||||
with open(_file, "rb") as f:
|
||||
data = f.read()
|
||||
data = data.replace(_find, _replace, 1)
|
||||
|
||||
with open(_file, "wb") as f:
|
||||
f.write(data)
|
||||
|
||||
|
||||
def _embed_git_data(self) -> None:
|
||||
"""
|
||||
Embed git data
|
||||
"""
|
||||
_file = self._application_output / "Contents" / "Info.plist"
|
||||
|
||||
_git_branch = self._git_branch or "Built from source"
|
||||
_git_commit = self._git_commit_url or ""
|
||||
_git_commit_date = self._git_commit_date or time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
|
||||
print("Embedding git data")
|
||||
_plist = plistlib.load(_file.open("rb"))
|
||||
_plist["Github"] = {
|
||||
"Branch": _git_branch,
|
||||
"Commit URL": _git_commit,
|
||||
"Commit Date": _git_commit_date
|
||||
}
|
||||
plistlib.dump(_plist, _file.open("wb"), sort_keys=True)
|
||||
|
||||
|
||||
def _embed_resources(self) -> None:
|
||||
"""
|
||||
Embed resources
|
||||
"""
|
||||
print("Embedding resources")
|
||||
for file in Path("payloads/Icon/AppIcons").glob("*.icns"):
|
||||
subprocess_wrapper.run_and_verify(
|
||||
["/bin/cp", str(file), self._application_output / "Contents" / "Resources/"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
|
||||
def generate(self) -> None:
|
||||
"""
|
||||
Generate OpenCore-Patcher.app
|
||||
"""
|
||||
self._embed_analytics_key()
|
||||
self._generate_application()
|
||||
self._remove_analytics_key()
|
||||
|
||||
self._patch_load_command()
|
||||
self._embed_git_data()
|
||||
self._embed_resources()
|
||||
133
ci_tooling/build_module/disk_images.py
Normal file
133
ci_tooling/build_module/disk_images.py
Normal file
@@ -0,0 +1,133 @@
|
||||
|
||||
import subprocess
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from opencore_legacy_patcher import constants
|
||||
from opencore_legacy_patcher.support import subprocess_wrapper
|
||||
|
||||
|
||||
|
||||
class GenerateDiskImages:
|
||||
|
||||
def __init__(self, reset_dmg_cache: bool = False) -> None:
|
||||
"""
|
||||
Initialize
|
||||
"""
|
||||
self.reset_dmg_cache = reset_dmg_cache
|
||||
|
||||
|
||||
def _delete_extra_binaries(self):
|
||||
"""
|
||||
Delete extra binaries from payloads directory
|
||||
"""
|
||||
|
||||
whitelist_folders = [
|
||||
"ACPI",
|
||||
"Config",
|
||||
"Drivers",
|
||||
"Icon",
|
||||
"Kexts",
|
||||
"OpenCore",
|
||||
"Tools",
|
||||
"Launch Services",
|
||||
]
|
||||
|
||||
whitelist_files = []
|
||||
|
||||
print("Deleting extra binaries...")
|
||||
for file in Path("payloads").glob(pattern="*"):
|
||||
if file.is_dir():
|
||||
if file.name in whitelist_folders:
|
||||
continue
|
||||
print(f"- Deleting {file.name}")
|
||||
subprocess_wrapper.run_and_verify(["/bin/rm", "-rf", file])
|
||||
else:
|
||||
if file.name in whitelist_files:
|
||||
continue
|
||||
print(f"- Deleting {file.name}")
|
||||
subprocess_wrapper.run_and_verify(["/bin/rm", "-f", file])
|
||||
|
||||
|
||||
|
||||
def _generate_payloads_dmg(self):
|
||||
"""
|
||||
Generate disk image containing all payloads
|
||||
Disk image will be password protected due to issues with
|
||||
Apple's notarization system and inclusion of kernel extensions
|
||||
"""
|
||||
|
||||
if Path("./payloads.dmg").exists():
|
||||
if self.reset_dmg_cache is False:
|
||||
print("- payloads.dmg already exists, skipping creation")
|
||||
return
|
||||
|
||||
print("- Removing old payloads.dmg")
|
||||
subprocess_wrapper.run_and_verify(
|
||||
["/bin/rm", "-rf", "./payloads.dmg"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
print("Generating DMG...")
|
||||
subprocess_wrapper.run_and_verify([
|
||||
'/usr/bin/hdiutil', 'create', './payloads.dmg',
|
||||
'-megabytes', '32000', # Overlays can only be as large as the disk image allows
|
||||
'-format', 'UDZO', '-ov',
|
||||
'-volname', 'OpenCore Patcher Resources (Base)',
|
||||
'-fs', 'HFS+',
|
||||
'-srcfolder', './payloads',
|
||||
'-passphrase', 'password', '-encryption'
|
||||
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
print("DMG generation complete")
|
||||
|
||||
|
||||
def _download_resources(self):
|
||||
"""
|
||||
Download required dependencies
|
||||
"""
|
||||
|
||||
patcher_support_pkg_version = constants.Constants().patcher_support_pkg_version
|
||||
required_resources = [
|
||||
"Universal-Binaries.dmg"
|
||||
]
|
||||
|
||||
print("Downloading required resources...")
|
||||
for resource in required_resources:
|
||||
if Path(f"./{resource}").exists():
|
||||
if self.reset_dmg_cache is True:
|
||||
print(f" - Removing old {resource}")
|
||||
# Just to be safe
|
||||
assert resource, "Resource cannot be empty"
|
||||
assert resource not in ("/", "."), "Resource cannot be root"
|
||||
subprocess_wrapper.run_and_verify(
|
||||
["/bin/rm", "-rf", f"./{resource}"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
else:
|
||||
print(f"- {resource} already exists, skipping download")
|
||||
continue
|
||||
|
||||
print(f"- Downloading {resource}...")
|
||||
|
||||
subprocess_wrapper.run_and_verify(
|
||||
[
|
||||
"/usr/bin/curl", "-LO",
|
||||
f"https://github.com/dortania/PatcherSupportPkg/releases/download/{patcher_support_pkg_version}/{resource}"
|
||||
],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
if not Path(f"./{resource}").exists():
|
||||
print(f"- {resource} not found")
|
||||
raise Exception(f"{resource} not found")
|
||||
|
||||
|
||||
def generate(self) -> None:
|
||||
"""
|
||||
Generate disk images
|
||||
"""
|
||||
|
||||
self._delete_extra_binaries()
|
||||
self._generate_payloads_dmg()
|
||||
self._download_resources()
|
||||
59
ci_tooling/build_module/package.py
Normal file
59
ci_tooling/build_module/package.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import macos_pkg_builder
|
||||
from opencore_legacy_patcher import constants
|
||||
|
||||
|
||||
class GeneratePackage:
|
||||
"""
|
||||
Generate OpenCore-Patcher.pkg
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
Initialize
|
||||
"""
|
||||
self._files = {
|
||||
"./dist/OpenCore-Patcher.app": "/Library/Application Support/Dortania/OpenCore-Patcher.app",
|
||||
"./ci_tooling/privileged_helper_tool/com.dortania.opencore-legacy-patcher.privileged-helper": "/Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper",
|
||||
}
|
||||
|
||||
|
||||
def _generate_welcome(self) -> str:
|
||||
"""
|
||||
Generate Welcome message for PKG
|
||||
"""
|
||||
_welcome = ""
|
||||
|
||||
_welcome = "# Overview\n"
|
||||
_welcome += f"This package will install the OpenCore Legacy Patcher application (v{constants.Constants().patcher_version}) on your system."
|
||||
|
||||
_welcome += "\n\nAdditionally, a shortcut for OpenCore Legacy Patcher will be added in the '/Applications' folder."
|
||||
_welcome += "\n\nThis package will not 'Build and Install OpenCore' or install any 'Root Patches' on your machine. If required, you can run OpenCore Legacy Patcher to install any patches you may need."
|
||||
_welcome += f"\n\nFor more information on OpenCore Legacy Patcher usage, see our [documentation]({constants.Constants().guide_link}) and [GitHub repository]({constants.Constants().repo_link})."
|
||||
_welcome += "\n\n"
|
||||
|
||||
_welcome += "## Files Installed"
|
||||
_welcome += "\n\nInstallation of this package will add the following files to your system:"
|
||||
for key, value in self._files.items():
|
||||
_welcome += f"\n\n- `{value}`"
|
||||
|
||||
return _welcome
|
||||
|
||||
|
||||
def generate(self) -> None:
|
||||
"""
|
||||
Generate OpenCore-Patcher.pkg
|
||||
"""
|
||||
print("Generating OpenCore-Patcher.pkg")
|
||||
assert macos_pkg_builder.Packages(
|
||||
pkg_output="./dist/OpenCore-Patcher.pkg",
|
||||
pkg_bundle_id="com.dortania.opencore-legacy-patcher",
|
||||
pkg_version=constants.Constants().patcher_version,
|
||||
pkg_allow_relocation=False,
|
||||
pkg_as_distribution=True,
|
||||
pkg_background="./ci_tooling/installation_pkg/PkgBackground.png",
|
||||
pkg_preinstall_script="./ci_tooling/installation_pkg/preinstall.sh",
|
||||
pkg_postinstall_script="./ci_tooling/installation_pkg/postinstall.sh",
|
||||
pkg_file_structure=self._files,
|
||||
pkg_title="OpenCore Legacy Patcher",
|
||||
pkg_welcome=self._generate_welcome(),
|
||||
).build() is True
|
||||
41
ci_tooling/build_module/sign_notarize.py
Normal file
41
ci_tooling/build_module/sign_notarize.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import mac_signing_buddy
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class SignAndNotarize:
|
||||
|
||||
def __init__(self, path: Path, signing_identity: str, notarization_apple_id: str, notarization_password: str, notarization_team_id: str, entitlements: str = None) -> None:
|
||||
"""
|
||||
Initialize
|
||||
"""
|
||||
self._path = path
|
||||
self._signing_identity = signing_identity
|
||||
self._notarization_apple_id = notarization_apple_id
|
||||
self._notarization_password = notarization_password
|
||||
self._notarization_team_id = notarization_team_id
|
||||
self._entitlements = entitlements
|
||||
|
||||
|
||||
def sign_and_notarize(self) -> None:
|
||||
"""
|
||||
Sign and Notarize
|
||||
"""
|
||||
if not all([self._signing_identity, self._notarization_apple_id, self._notarization_password, self._notarization_team_id]):
|
||||
print("Signing and Notarization details not provided, skipping")
|
||||
return
|
||||
|
||||
print(f"Signing {self._path.name}")
|
||||
mac_signing_buddy.Sign(
|
||||
identity=self._signing_identity,
|
||||
file=self._path,
|
||||
**({"entitlements": self._entitlements} if self._entitlements else {}),
|
||||
).sign()
|
||||
|
||||
print(f"Notarizing {self._path.name}")
|
||||
mac_signing_buddy.Notarize(
|
||||
apple_id=self._notarization_apple_id,
|
||||
password=self._notarization_password,
|
||||
team_id=self._notarization_team_id,
|
||||
file=self._path,
|
||||
).sign()
|
||||
BIN
ci_tooling/installation_pkg/PkgBackground.png
Normal file
BIN
ci_tooling/installation_pkg/PkgBackground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
64
ci_tooling/installation_pkg/postinstall.sh
Normal file
64
ci_tooling/installation_pkg/postinstall.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/bin/zsh --no-rcs
|
||||
# ------------------------------------------------------
|
||||
# OpenCore Legacy Patcher PKG Post Install Script
|
||||
# ------------------------------------------------------
|
||||
# Set SUID bit on helper tool, and create app alias.
|
||||
# ------------------------------------------------------
|
||||
|
||||
|
||||
# MARK: Variables
|
||||
# ---------------------------
|
||||
|
||||
helperPath="/Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
|
||||
mainAppPath="/Library/Application Support/Dortania/OpenCore-Patcher.app"
|
||||
shimAppPath="/Applications/OpenCore-Patcher.app"
|
||||
|
||||
|
||||
# MARK: Functions
|
||||
# ---------------------------
|
||||
|
||||
function _setSUIDBit() {
|
||||
local binaryPath=$1
|
||||
|
||||
echo " Setting SUID bit on: $binaryPath"
|
||||
|
||||
# Check if path is a directory
|
||||
if [[ -d $binaryPath ]]; then
|
||||
/bin/chmod -R +s $binaryPath
|
||||
else
|
||||
/bin/chmod +s $binaryPath
|
||||
fi
|
||||
}
|
||||
|
||||
function _createAlias() {
|
||||
local mainPath=$1
|
||||
local aliasPath=$2
|
||||
|
||||
# Check if alias path exists
|
||||
if [[ -e $aliasPath ]]; then
|
||||
# Check if alias path is a symbolic link
|
||||
if [[ -L $aliasPath ]]; then
|
||||
echo " Removing old symbolic link: $aliasPath"
|
||||
/bin/rm -f $aliasPath
|
||||
else
|
||||
echo " Removing old file: $aliasPath"
|
||||
/bin/rm -rf $aliasPath
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create symbolic link
|
||||
echo " Creating symbolic link: $aliasPath"
|
||||
/bin/ln -s $mainPath $aliasPath
|
||||
}
|
||||
|
||||
function _main() {
|
||||
_setSUIDBit $helperPath
|
||||
_createAlias $mainAppPath $shimAppPath
|
||||
}
|
||||
|
||||
|
||||
# MARK: Main
|
||||
# ---------------------------
|
||||
|
||||
echo "Starting postinstall script..."
|
||||
_main
|
||||
69
ci_tooling/installation_pkg/preinstall.sh
Normal file
69
ci_tooling/installation_pkg/preinstall.sh
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/bin/zsh --no-rcs
|
||||
# ------------------------------------------------------
|
||||
# OpenCore Legacy Patcher PKG Preinstall Script
|
||||
# ------------------------------------------------------
|
||||
# Remove old files, and prepare directories.
|
||||
# ------------------------------------------------------
|
||||
|
||||
|
||||
# MARK: Variables
|
||||
# ---------------------------
|
||||
|
||||
filesToRemove=(
|
||||
"/Applications/OpenCore-Patcher.app"
|
||||
"/Library/Application Support/Dortania/Update.plist"
|
||||
"/Library/Application Support/Dortania/OpenCore-Patcher.app"
|
||||
"/Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
|
||||
)
|
||||
|
||||
|
||||
# MARK: Functions
|
||||
# ---------------------------
|
||||
|
||||
function _removeFile() {
|
||||
local file=$1
|
||||
|
||||
if [[ ! -e $file ]]; then
|
||||
# Check if file is a symbolic link
|
||||
if [[ -L $file ]]; then
|
||||
echo " Removing symbolic link: $file"
|
||||
/bin/rm -f $file
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
echo " Removing file: $file"
|
||||
|
||||
# Check if file is a directory
|
||||
if [[ -d $file ]]; then
|
||||
/bin/rm -rf $file
|
||||
else
|
||||
/bin/rm -f $file
|
||||
fi
|
||||
}
|
||||
|
||||
function _createParentDirectory() {
|
||||
local file=$1
|
||||
|
||||
local parentDirectory=$(/usr/bin/dirname $file)
|
||||
|
||||
# Check if parent directory exists
|
||||
if [[ ! -d $parentDirectory ]]; then
|
||||
echo " Creating parent directory: $parentDirectory"
|
||||
/bin/mkdir -p $parentDirectory
|
||||
fi
|
||||
}
|
||||
|
||||
function _main() {
|
||||
for file in $filesToRemove; do
|
||||
_removeFile $file
|
||||
_createParentDirectory $file
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# MARK: Main
|
||||
# ---------------------------
|
||||
|
||||
echo "Starting preinstall script..."
|
||||
_main
|
||||
@@ -5,4 +5,6 @@ pyinstaller
|
||||
packaging
|
||||
py_sip_xnu
|
||||
py-applescript
|
||||
markdown2
|
||||
markdown2
|
||||
macos-pkg-builder
|
||||
mac-signing-buddy
|
||||
Reference in New Issue
Block a user