Skip to content
This repository has been archived by the owner on Aug 19, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'Tribler/main' into highlander
Browse files Browse the repository at this point in the history
  • Loading branch information
qstokkink committed Jun 19, 2024
2 parents a4f213a + e4a99f4 commit 136e8c8
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 49 deletions.
38 changes: 38 additions & 0 deletions build/mac/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# MacOS Build and Signing Procedure

## Introduction
This README outlines the procedures for building and signing the MacOS application and DMG installer for the Tribler project. We have updated the build system to streamline the signing process and centralize the build environment.

## Build System Overview

### Script Separation
To improve maintainability and clarity, the signing process has been separated from the main build script:
- **Application Signing**: `sign_app.sh` is used to sign the `.app` file.
- **DMG Signing**: `sign_dmg.sh` is used to sign the `.dmg` file.

### Environment Configuration
Environment variables are isolated in the `env.sh` file under `./build/mac/`, allowing for easier management of build settings.

### Jenkins Integration
The build process is now performed on a dedicated `mac_mini` hosted on Jenkins, removing the reliance on externally dependent machines.

## Build and Signing Process
Follow these steps to build and sign the Tribler application for MacOS:

1. **Set Environment Variables**: Configure necessary variables in `./build/mac/env.sh`.
2. **Initialize Virtual Environment**: Prepare the virtual environment for build operations.
3. **Build the Binary**: Use Python packaging tools like PyInstaller or CxFreeze to compile the application.
4. **Sign the App**: Execute `./build/mac/sign_app.sh` to sign the `.app` file.
5. **Create DMG Installer**: Assemble the DMG file that will contain the application.
6. **Sign the DMG File**: Run `./build/mac/sign_dmg.sh` to sign the DMG and submit it to the Apple Notary service for notarization.

## Conditions for Signing
The signing scripts will only execute if the following conditions are met, ensuring security and compliance:
- `CODE_SIGN_ENABLED` is set to enable signing.
- `APPLE_DEV_ID` is provided to specify the developer ID used for signing.

## Repository Links
- **Build Script**: `./build/mac/makedist_macos.sh`
- **Environment Settings**: `./build/mac/env.sh`
- **App Signing Script**: `./build/mac/sign_app.sh`
- **DMG Signing Script**: `./build/mac/sign_dmg.sh`
36 changes: 36 additions & 0 deletions build/mac/env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -x # print all commands
set -e # exit when any command fails

export APPNAME=Tribler
export LOG_LEVEL=${LOG_LEVEL:-"DEBUG"}
export BUILD_ENV=${BUILD_ENV:-"venv"}

PRE_BUILD_INSTRUCTIONS=$(cat <<-END
git describe --tags | python -c "import sys; print(next(sys.stdin).lstrip('v'))" > .TriblerVersion
git rev-parse HEAD > .TriblerCommit
export TRIBLER_VERSION=\$(head -n 1 .TriblerVersion)
python3 ./build/update_version.py -r .
END
)

if [ ! -f .TriblerVersion ]; then
echo "No .TriblerVersion file found, run the following commands:"
echo "$PRE_BUILD_INSTRUCTIONS"
exit 1
fi

if [ -e .TriblerVersion ]; then
export DMGNAME="Tribler-$(cat .TriblerVersion)"
fi

# Directories
export DIST_DIR=dist
export INSTALL_DIR=$DIST_DIR/installdir
export TEMP_DIR=$DIST_DIR/temp
export RESOURCES_DIR=build/mac/resources

# Environment variables related to signing
export CODE_SIGN_ENABLED=${CODE_SIGN_ENABLED:-""}
export APPLE_DEV_ID=${APPLE_DEV_ID:-""}
58 changes: 21 additions & 37 deletions build/mac/makedist_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,10 @@ set -e # exit when any command fails
# Script to build Tribler 64-bit on Mac
# Initial author(s): Riccardo Petrocco, Arno Bakker

APPNAME=Tribler
LOG_LEVEL=${LOG_LEVEL:-"DEBUG"}
BUILD_ENV=${BUILD_ENV:-"venv"}

if [ -e .TriblerVersion ]; then
DMGNAME="Tribler-$(cat .TriblerVersion)"
fi

export RESOURCES=build/mac/resources
source ./build/mac/env.sh

# ----- Clean up
/bin/rm -rf dist
/bin/rm -rf $DIST_DIR

# ----- Prepare venv & install dependencies before the build

Expand All @@ -29,39 +21,35 @@ python3 -m pip install --upgrade -r requirements-build.txt

pyinstaller tribler.spec --log-level="${LOG_LEVEL}"

mkdir -p dist/installdir
mv dist/$APPNAME.app dist/installdir
mkdir -p $INSTALL_DIR
mv $DIST_DIR/$APPNAME.app $INSTALL_DIR

# From original Makefile
# Background
mkdir -p dist/installdir/.background
cp $RESOURCES/background.png dist/installdir/.background
mkdir -p $INSTALL_DIR/.background
cp $RESOURCES_DIR/background.png $INSTALL_DIR/.background

# Volume Icon
cp $RESOURCES/VolumeIcon.icns dist/installdir/.VolumeIcon.icns
cp $RESOURCES_DIR/VolumeIcon.icns $INSTALL_DIR/.VolumeIcon.icns

# Shortcut to /Applications
ln -s /Applications dist/installdir/Applications
ln -s /Applications $INSTALL_DIR/Applications

touch dist/installdir
touch $INSTALL_DIR

mkdir -p dist/temp
mkdir -p $TEMP_DIR

# Sign the app if environment variables are set
if [ -n "$CODE_SIGN_ENABLED" ] && [ -n "$APPLE_DEV_ID" ]; then
echo "Signing $APPNAME.app with ID: $APPLE_DEV_ID"
SIGN_MSG="Developer ID Application: $APPLE_DEV_ID"
codesign --deep --force --verbose --sign "$SIGN_MSG" --options runtime dist/installdir/$APPNAME.app
fi
./build/mac/sign_app.sh

# create image
hdiutil create -fs HFS+ -srcfolder dist/installdir -format UDRW -scrub -volname ${APPNAME} dist/$APPNAME.dmg
hdiutil create -fs HFS+ -srcfolder $INSTALL_DIR -format UDRW -scrub -volname ${APPNAME} $DIST_DIR/$APPNAME.dmg

# open it
hdiutil attach -readwrite -noverify -noautoopen dist/$APPNAME.dmg -mountpoint dist/temp/mnt
hdiutil attach -readwrite -noverify -noautoopen $DIST_DIR/$APPNAME.dmg -mountpoint $TEMP_DIR/mnt

# make sure root folder is opened when image is
bless --folder dist/temp/mnt --openfolder dist/temp/mnt
bless --folder $TEMP_DIR/mnt --openfolder $TEMP_DIR/mnt
# hack: wait for completion
sleep 1

Expand Down Expand Up @@ -100,23 +88,19 @@ osascript -e "tell application \"Finder\"" \
-e "end tell" || true

# turn on custom volume icon
SetFile -a C dist/temp/mnt || true
SetFile -a C $TEMP_DIR/mnt || true

# close
hdiutil detach dist/temp/mnt || true
hdiutil detach $TEMP_DIR/mnt || true

# make read-only
mv dist/$APPNAME.dmg dist/temp/rw.dmg
hdiutil convert dist/temp/rw.dmg -format UDZO -imagekey zlib-level=9 -o dist/$APPNAME.dmg
rm -f dist/temp/rw.dmg
mv $DIST_DIR/$APPNAME.dmg $TEMP_DIR/rw.dmg
hdiutil convert $TEMP_DIR/rw.dmg -format UDZO -imagekey zlib-level=9 -o $DIST_DIR/$APPNAME.dmg
rm -f $TEMP_DIR/rw.dmg

if [ ! -z "$DMGNAME" ]; then
mv dist/$APPNAME.dmg dist/$DMGNAME.dmg
mv $DIST_DIR/$APPNAME.dmg $DIST_DIR/$DMGNAME.dmg
fi

# Sign the dmg package and verify it
if [ -n "$CODE_SIGN_ENABLED" ] && [ -n "$APPLE_DEV_ID" ]; then
codesign --force --verify --verbose --sign "$SIGN_MSG" dist/$DMGNAME.dmg
codesign --verify --verbose=4 dist/$DMGNAME.dmg
spctl --assess --type open --context context:primary-signature -v dist/$DMGNAME.dmg
fi
./build/mac/sign_dmg.sh
26 changes: 26 additions & 0 deletions build/mac/sign_app.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
set -x # print all commands
set -e # exit when any command fails

source ./build/mac/env.sh

# App file to sign
APP_FILE=$INSTALL_DIR/$APPNAME.app
if [ -z "$APP_FILE" ]; then
echo "$APP_FILE file not found"
exit 1
fi

if [ -z "$CODE_SIGN_ENABLED" ]; then
echo "Code sign is not enabled. Skipping code signing the app $APP_FILE."
exit 0
fi

if [ -z "$APPLE_DEV_ID" ]; then
echo "Code sign is enabled but Apple Dev ID is not set. Exiting with failure"
exit 1
fi

echo "Signing $APP_FILE with Apple Dev ID: $APPLE_DEV_ID"
SIGN_MSG="Developer ID Application: $APPLE_DEV_ID"
codesign --deep --force --verbose --sign "$SIGN_MSG" --options runtime $APP_FILE
36 changes: 36 additions & 0 deletions build/mac/sign_dmg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash
set -x # print all commands
set -e # exit when any command fails

source ./build/mac/env.sh

DMG_FILE=$DIST_DIR/$DMGNAME.dmg
if [ -z "$DMG_FILE" ]; then
echo "$DMG_FILE file not found"
exit 1
fi

if [ -z "$CODE_SIGN_ENABLED" ]; then
echo "Code sign is not enabled. Skipping code signing the installer $DMG_FILE."
exit 0
fi

if [ -z "$APPLE_DEV_ID" ]; then
echo "Code sign is enabled but Apple Dev ID is not set. Exiting with failure"
exit 1
fi

# Sign the dmg package and verify it
SIGN_MSG="Developer ID Application: $APPLE_DEV_ID"
codesign --force --verify --verbose --sign "$SIGN_MSG" $DMG_FILE
codesign --verify --verbose=4 $DMG_FILE

# Assuming the keychain profile with the signing key is created and named as "tribler-codesign-profile".
# If not create the keychain profile with the following command:
# xcrun notarytool store-credentials "tribler-codesign-profile" --apple-id "<dev-id-email>" --team-id "<dev-id-team>"
KEYCHAIN_PROFILE=${KEYCHAIN_PROFILE:-"tribler-codesign-profile"}
# Submit the DMG for notarization and staple afterwards
xcrun notarytool submit $DMG_FILE --keychain-profile "$KEYCHAIN_PROFILE" --wait
xcrun stapler staple $DMG_FILE
# Verify the notarization
spctl --assess --type open --context context:primary-signature -v $DMG_FILE
7 changes: 0 additions & 7 deletions src/tribler/gui/tribler_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ def __init__(self, app_manager: AppManager, root_state_dir: Path, api_port: int,
self.tribler_core_test_exception_shortcut = QShortcut(QKeySequence("Ctrl+Alt+Shift+C"), self)
connect(self.tribler_core_test_exception_shortcut.activated, self.on_test_tribler_core_exception)

connect(self.top_search_bar.clicked, self.clicked_search_bar)
connect(self.top_search_bar.returnPressed, self.on_top_search_bar_return_pressed)

# Remove the focus rect on OS X
Expand Down Expand Up @@ -770,12 +769,6 @@ def deselect_all_menu_buttons(self, except_select=None):
button.setEnabled(True)
button.setChecked(False)

def clicked_search_bar(self, checked=False):
query = self.top_search_bar.text()
if query and self.search_results_page.has_results:
self.deselect_all_menu_buttons()
self.stackedWidget.setCurrentIndex(PAGE_SEARCH_RESULTS)

def on_top_search_bar_return_pressed(self):
query_text = self.top_search_bar.text()
if not query_text:
Expand Down
2 changes: 0 additions & 2 deletions src/tribler/gui/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,6 @@ def html_label(text, background="#e4e4e4", color="#222222", bold=True):

def votes_count(votes=0.0):
votes = float(votes)
# FIXME: this is a temp fix to cap the normalized value to 1.
# The votes should already be normalized before formatting it.
votes = max(0.0, min(votes, 1.0))
# We add sqrt to flatten the votes curve a bit
votes = math.sqrt(votes)
Expand Down
2 changes: 1 addition & 1 deletion src/tribler/gui/widgets/popular/popular_torrents_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


class PopularTorrentsModel(ChannelContentModel):
columns_shown = (Column.CATEGORY, Column.NAME, Column.SIZE, Column.CREATED)
columns_shown = (Column.CATEGORY, Column.NAME, Column.SIZE, Column.HEALTH, Column.CREATED)

def __init__(self, *args, **kwargs):
super().__init__(*args, endpoint_url="metadata/torrents/popular", **kwargs)
2 changes: 0 additions & 2 deletions src/tribler/gui/widgets/tablecontentdelegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ def __init__(self, parent=None):
self.hovering_over_tag_edit_button: bool = False
self.hovering_over_download_popular_torrent_button: int = -1

# TODO: restore this behavior, so there is really some tolerance zone!
# We have to control if mouse is in the buttons box to add some tolerance for vertical mouse
# misplacement around the buttons. The button box effectively overlaps upper and lower rows.
# row 0
Expand Down Expand Up @@ -565,7 +564,6 @@ class TriblerContentDelegate(
SnippetCreatedColumnMixin,
):
def __init__(self, table_view, parent=None):
# TODO: refactor this not to rely on inheritance order, but instead use interface method pattern
TriblerButtonsDelegate.__init__(self, parent)

self.download_button = DownloadIconButton()
Expand Down

0 comments on commit 136e8c8

Please sign in to comment.