mirror of
https://github.com/warpdotdev/warp.git
synced 2026-05-22 23:32:19 +08:00
## Description <!-- Please remember to add your design buddy onto the PR for review, if it contains any UI changes! --> Implementation of improving heuristics: by allocating more traffic to nld new classifier; This should resolve misfires as shell for file path or url ## Linked Issue <!-- Link the GitHub issue this PR addresses. Before opening this PR, please confirm: --> - [ ] The linked issue is labeled `ready-to-spec` or `ready-to-implement`. - [ ] Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes). ## Testing <!-- How did you test this change? What automated tests did you add? If you didn't add any new tests, what's your justification for not adding any? Manual testing is required for changes that can be manually tested, and almost all changes can be manually tested. If your change can be manually tested, please include screenshots or a screen recording that show it working end to end. You can run the app locally using `./script/run` - see WARP.md for more details on how to get set up. --> `RUST_LOG=debug ./script/run --features nld_heuristic_v2` `RUST_LOG=debug ./script/run --features nld_classifier_v2, nld_heuristic_v2` - [x] I have manually tested my changes locally with `./script/run` ### Screenshots / Videos <!-- Attach screenshots or a short video demonstrating the change, where appropriate. Remove this section if it is not relevant to your PR. --> Test 543 misfire `read this https://trilogy-eng.atlassian.net/browse/epmlive-17588` - it should be true/shell in v1 and false/non-shell in v2 - with `nld_heuristic_v2` and `nld_classifier_v2`, we could see now classifier could classify this one to prompt <img width="2169" height="336" alt="image" src="https://github.com/user-attachments/assets/d6129bc0-dba6-4ecd-9aab-8f36c64f63c8" /> <img width="2158" height="543" alt="image" src="https://github.com/user-attachments/assets/fc698d9d-9cea-4be1-874f-32f881c6fe02" /> <img width="1315" height="187" alt="image" src="https://github.com/user-attachments/assets/ebc989de-f344-4ddb-82ae-a145f55766aa" /> <img width="2168" height="350" alt="image" src="https://github.com/user-attachments/assets/578eccb0-949d-4a1c-a394-ef95711c7af0" /> ## Agent Mode - [ ] Warp Agent Mode - This PR was created via Warp's AI Agent Mode <!-- ## Changelog Entries for Stable The entries below will be used when constructing a soft-copy of the stable release changelog. Leave blank or remove the lines if no entry in the stable changelog is needed. Entries should be on the same line, without the `{{` `}}` brackets. You can use multiple lines, even of the same type. The valid suffixes are: - NEW-FEATURE: for new, relatively sizable features. Features listed here will likely have docs / social media posts / marketing launches associated with them, so use sparingly. - IMPROVEMENT: for new functionality of existing features. - BUG-FIX: for fixes related to known bugs or regressions. - IMAGE: the image specified by the URL (hosted on GCP) will be added to Dev & Preview releases. For Stable releases, see the pinned doc in the #release Slack channel. - OZ: Oz-related updates. Use `CHANGELOG-OZ`. At most 4 Oz updates are shown in-app per release. - NONE: Explicitly opt out of changelog inclusion. Use `CHANGELOG-NONE` for PRs that should never appear in the changelog (e.g. refactors, internal tooling, CI changes). This prevents the changelog agent from inferring an entry. CHANGELOG-NEW-FEATURE: {{text goes here...}} CHANGELOG-IMPROVEMENT: {{text goes here...}} CHANGELOG-BUG-FIX: {{text goes here...}} CHANGELOG-BUG-FIX: {{more text goes here...}} CHANGELOG-IMAGE: {{GCP-hosted URL goes here...}} CHANGELOG-OZ: {{text goes here...}} CHANGELOG-NONE -->
850 lines
32 KiB
Bash
Executable File
850 lines
32 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Bundle the application for distribution.
|
|
#
|
|
# See the parameter parsing section below for available options.
|
|
#
|
|
# Note that there are several steps to complete before the app is ready to
|
|
# be distributed, one of which is asynchronous and requires apple to process
|
|
# our binary.
|
|
#
|
|
# The exact steps depend on which artifact we are building, the desktop app or the CLI. Overall,
|
|
# the steps are:
|
|
#
|
|
# 1) Create the binary or mac bundle by running `cargo`.
|
|
# 2) Create a keychain based on our distribution cert.
|
|
# 3) Codesign the built artifact using the keychain.
|
|
#
|
|
# Additionally, for an app, we create a dmg:
|
|
# 4) Create the dmg using `hdiutil create`.
|
|
# 5) Codesign our dmg using the keychain.
|
|
# 6) Upload the app to Apple for it to be notarized - this is async, and we
|
|
# poll until it is done.
|
|
# 7) "Staple" the notarization to the dmg.
|
|
#
|
|
# Once the stapling is done, the app can be shared.
|
|
#
|
|
# Three passwords are read from GCP Secret Manager (or from env if --read-passwords-from-env is set) if you are codesigning.
|
|
# 1) WARP_NOTARIZATION_PASSWORD: This is an "app-specific password" that
|
|
# is tied to the zach@warp.dev account. See https://support.apple.com/en-us/HT204397
|
|
# 2) WARP_DEVELOPER_ID_CERT_PASSWORD: This is a password tied to the private key
|
|
# of our cert - it is needed to use the cert to sign our binary.
|
|
# 3) WARP_CODESIGN_KEYCHAIN_PASSWORD: This is an arbitrary password only used
|
|
# in the lifetime of this app for creating the keychain used to sign. Can
|
|
# be anything.
|
|
#
|
|
# See
|
|
# https://github.com/burtonageo/cargo-bundle
|
|
# https://wiki.lazarus.freepascal.org/Code_Signing_for_macOS
|
|
# https://wiki.lazarus.freepascal.org/Notarization_for_macOS_10.14.5%2B
|
|
# https://developer.apple.com/developer-id/
|
|
# https://github.com/atom/atom/blob/976cb9ef3a611163052f9d31c6c3685dc1e6c5b4/script/lib/code-sign-on-mac.js
|
|
|
|
set -e
|
|
|
|
# Determine the repository root directory
|
|
WORKSPACE_ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
|
|
# This is used to set the minimum deployment target for mac
|
|
# https://cmake.org/cmake/help/latest/envvar/MACOSX_DEPLOYMENT_TARGET.html
|
|
# If unset, it uses the system one, but we want to build for older versions
|
|
# of mac os by default.
|
|
#
|
|
# This should be kept in sync with the definition of this variable in
|
|
# `.cargo/config.toml`.
|
|
export MACOSX_DEPLOYMENT_TARGET="10.14"
|
|
|
|
# Constants used later in the script.
|
|
INTEL_ARCH="x86_64"
|
|
INTEL_TARGET="$INTEL_ARCH-apple-darwin"
|
|
ARM_ARCH="aarch64"
|
|
ARM_TARGET="$ARM_ARCH-apple-darwin"
|
|
DEFAULT_ARCH="$(rustc --print cfg | grep target_arch)"
|
|
|
|
# Function to clean up temporary DMG files
|
|
cleanup_dmg_files() {
|
|
local target_dir="$1"
|
|
if [ -d "$target_dir" ]; then
|
|
echo "Cleaning up temporary DMG files in $target_dir"
|
|
find "$target_dir" -name "*.dmg" -type f -delete
|
|
find "$target_dir" -name "rw.*.dmg" -type f -delete
|
|
fi
|
|
# Also check if any volumes are mounted and unmount them
|
|
hdiutil info | grep "/Volumes/Warp.*" | awk '{print $1}' | while read -r disk; do
|
|
echo "Unmounting disk image: $disk"
|
|
hdiutil detach "$disk" -force || true
|
|
done
|
|
}
|
|
|
|
# Clean up the temporary codesigning keychain.
|
|
cleanup_codesign_keychain() {
|
|
if [[ "${CODESIGN:-false}" = true && -n "${CODESIGN_KEYCHAIN_NAME:-}" ]]; then
|
|
echo "Cleaning up by deleting $CODESIGN_KEYCHAIN_NAME keychain."
|
|
security delete-keychain "$CODESIGN_KEYCHAIN_NAME" || echo "No keychain to delete or already deleted."
|
|
fi
|
|
}
|
|
|
|
# Set up cleanup trap
|
|
trap 'cleanup_dmg_files "$DMG_DIR"; cleanup_codesign_keychain' EXIT
|
|
|
|
# Define a helper function that uses Python to compute a relative path.
|
|
function relpath() {
|
|
python -c "import os,sys;print(os.path.relpath(*(sys.argv[1:])))" "$@";
|
|
}
|
|
|
|
# Defaults for command-line flags.
|
|
UNIVERSAL_BINARY=true
|
|
BUILD_BINARY=true
|
|
TARGET_ARCH=""
|
|
DMG_NAME_SUFFIX=""
|
|
# By default we build dev bundles.
|
|
RELEASE_CHANNEL="dev"
|
|
FEATURES="release_bundle,cocoa_sentry,extern_plist"
|
|
REGISTER_SERVICES=true
|
|
DEBUG=false
|
|
ARTIFACT="app"
|
|
CODESIGN=true
|
|
SELFSIGN=false
|
|
OPEN_AFTER_BUNDLE=false
|
|
READ_PASSWORDS_FROM_ENV=false
|
|
|
|
PARAMS=""
|
|
while (( "$#" )); do
|
|
case "$1" in
|
|
# Speed up compilation time by only compiling a debug version of the app,
|
|
# rather than a release version
|
|
--debug)
|
|
DEBUG=true
|
|
shift
|
|
;;
|
|
# Only run `cargo check` without producing a bundle
|
|
--check-only)
|
|
echo 'Only running `cargo check` and not producing a bundle.'
|
|
CHECK_ONLY="true"
|
|
shift
|
|
;;
|
|
# Skip building the binary (assume it's already built)
|
|
--skip-build)
|
|
echo "Skipping binary build step."
|
|
BUILD_BINARY=false
|
|
shift
|
|
;;
|
|
# Skip code signing process
|
|
--nosign)
|
|
echo "Skipping code signing."
|
|
CODESIGN=false
|
|
SELFSIGN=false
|
|
shift
|
|
;;
|
|
# Sign with a local Apple Development cert instead of the official Warp cert.
|
|
# Useful for local debug builds when you don't have access to the company signing key.
|
|
# Falls back to ad-hoc signing if no Apple Development cert is found.
|
|
--selfsign)
|
|
echo "Self-signing enabled."
|
|
CODESIGN=false
|
|
SELFSIGN=true
|
|
shift
|
|
;;
|
|
# Build only for the default target architecture instead of universal binary
|
|
--nouniversal)
|
|
echo "Only building for default target $DEFAULT_TARGET, not a universal binary."
|
|
UNIVERSAL_BINARY=false
|
|
shift
|
|
;;
|
|
# Build only for a specific architecture (implies --nouniversal)
|
|
--arch)
|
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
|
if [ "$2" = "x86_64" -o "$2" = "aarch64" ]; then
|
|
echo "Building for specific architecture: $2"
|
|
TARGET_ARCH=$2
|
|
UNIVERSAL_BINARY=false
|
|
shift 2
|
|
else
|
|
echo "Error: --arch must be either x86_64 or aarch64, got '$2'" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Error: Argument for $1 is missing" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
# Set a custom suffix for the DMG file
|
|
--dmg-name-suffix)
|
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
|
echo "Setting custom DMG name suffix to $2"
|
|
DMG_NAME_SUFFIX=$2
|
|
shift 2
|
|
else
|
|
echo "Error: Argument for $1 is missing" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
# Open the parent directory after bundling completes.
|
|
-o|--open)
|
|
OPEN_AFTER_BUNDLE=true
|
|
shift
|
|
;;
|
|
# Specify the release channel (local, dev, preview, stable, oss)
|
|
-c|--channel)
|
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
|
RELEASE_CHANNEL=$2
|
|
shift 2
|
|
else
|
|
echo "Error: Argument for $1 is missing" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
# Set a specific Git release tag for the build
|
|
--release-tag)
|
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
|
echo "Setting release tag to $2"
|
|
export GIT_RELEASE_TAG=$2
|
|
shift 2
|
|
else
|
|
echo "Error: Argument for $1 is missing" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
# Read codesigning passwords from environment variables instead of GCP secret manager
|
|
--read-passwords-from-env)
|
|
echo "Reading codesigning passwords from env."
|
|
READ_PASSWORDS_FROM_ENV=true
|
|
shift
|
|
;;
|
|
--features)
|
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
|
echo "Adding Cargo features: $2"
|
|
FEATURES="$FEATURES,$2"
|
|
shift 2
|
|
else
|
|
echo "Error: Argument for $1 is missing" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
--artifact)
|
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
|
if [[ "$2" != "app" && "$2" != "cli" ]]; then
|
|
echo "Error: --artifact must be either 'app' or 'cli', got '$2'" >&2
|
|
exit 1
|
|
fi
|
|
ARTIFACT="$2"
|
|
shift 2
|
|
else
|
|
echo "Error: Argument for $1 is missing" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
*) # preserve positional arguments
|
|
PARAMS="$PARAMS $1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
# set positional arguments in their proper place
|
|
eval set -- "$PARAMS"
|
|
|
|
# Infer a cargo profile from the bundle configuration.
|
|
if [[ $DEBUG = true ]]; then
|
|
CARGO_PROFILE="dev"
|
|
elif [[ $RELEASE_CHANNEL = "local" || $RELEASE_CHANNEL = "dev" ]]; then
|
|
# For dev bundles, we want to enable debug assertions to
|
|
# catch violations that would otherwise silently pass in
|
|
# a normal release build (e.g. in stable).
|
|
if [[ "$ARTIFACT" == "cli" ]]; then
|
|
CARGO_PROFILE="release-cli-debug_assertions"
|
|
else
|
|
CARGO_PROFILE="release-lto-debug_assertions"
|
|
fi
|
|
else
|
|
if [[ "$ARTIFACT" == "cli" ]]; then
|
|
CARGO_PROFILE="release-cli"
|
|
else
|
|
CARGO_PROFILE="release-lto"
|
|
fi
|
|
fi
|
|
|
|
TARGET_PROFILE_DIR="$CARGO_PROFILE"
|
|
if [[ "$CARGO_PROFILE" == "dev" ]]; then
|
|
TARGET_PROFILE_DIR="debug"
|
|
fi
|
|
|
|
if [[ $RELEASE_CHANNEL = "local" ]]; then
|
|
WARP_BIN="warp"
|
|
BUNDLE_ID="dev.warp.Warp-Local"
|
|
WARP_APP_NAME="WarpLocal"
|
|
WARP_SCHEME_NAME="warplocal"
|
|
FEATURES="$FEATURES,agent_mode_debug"
|
|
# For local builds, use different versions of our bundled frameworks (e.g.:
|
|
# Sentry). This needs to be exported so it can be referenced by
|
|
# app/build.rs later, while running `cargo bundle`.
|
|
export FRAMEWORK_OVERRIDE="dev"
|
|
elif [[ $RELEASE_CHANNEL = "dev" ]]; then
|
|
WARP_BIN="dev"
|
|
BUNDLE_ID="dev.warp.Warp-Dev"
|
|
WARP_APP_NAME="WarpDev"
|
|
WARP_SCHEME_NAME="warpdev"
|
|
FEATURES="$FEATURES,agent_mode_debug"
|
|
# Enable heap usage tracking & profiling using jemalloc through pprof.
|
|
FEATURES="$FEATURES,jemalloc_pprof,heap_usage_tracking"
|
|
# For dev builds, use different versions of our bundled frameworks (e.g.:
|
|
# Sentry). This needs to be exported so it can be referenced by
|
|
# app/build.rs later, while running `cargo bundle`.
|
|
export FRAMEWORK_OVERRIDE="dev"
|
|
export HANDLE_MARKDOWN=1
|
|
elif [[ $RELEASE_CHANNEL = "preview" ]]; then
|
|
WARP_BIN="preview"
|
|
BUNDLE_ID="dev.warp.Warp-Preview"
|
|
WARP_APP_NAME="WarpPreview"
|
|
WARP_SCHEME_NAME="warppreview"
|
|
FEATURES="$FEATURES,preview_channel"
|
|
# Enable heap usage tracking & profiling using jemalloc through pprof.
|
|
FEATURES="$FEATURES,jemalloc_pprof,heap_usage_tracking"
|
|
elif [[ $RELEASE_CHANNEL = "stable" ]]; then
|
|
WARP_BIN="stable"
|
|
BUNDLE_ID="dev.warp.Warp-Stable"
|
|
WARP_APP_NAME="Warp"
|
|
WARP_SCHEME_NAME="warp"
|
|
# Enable heap usage tracking & profiling using jemalloc through pprof.
|
|
FEATURES="$FEATURES,jemalloc_pprof,heap_usage_tracking"
|
|
elif [[ $RELEASE_CHANNEL = "oss" ]]; then
|
|
WARP_BIN="warp-oss"
|
|
BUNDLE_ID="dev.warp.WarpOss"
|
|
WARP_APP_NAME="WarpOss"
|
|
WARP_SCHEME_NAME="warposs"
|
|
# The OSS channel does not ship Sentry, so drop the cocoa_sentry feature
|
|
# (which would otherwise pull in the Sentry framework dependency).
|
|
FEATURES="release_bundle,extern_plist"
|
|
fi
|
|
|
|
OUT_DIR="target/$TARGET_PROFILE_DIR/bundle/osx"
|
|
DOCK_TILE_PLUGIN_DIR="target/$TARGET_PROFILE_DIR/WarpDockTilePlugin.docktileplugin"
|
|
|
|
# Handle specific architecture targeting
|
|
if [[ -n "$TARGET_ARCH" ]]; then
|
|
# Building for a specific architecture
|
|
if [[ "$TARGET_ARCH" == "$INTEL_ARCH" ]]; then
|
|
echo "Building specifically for $INTEL_TARGET"
|
|
DEFAULT_TARGET="$INTEL_TARGET"
|
|
BUNDLE_DIR="target/$INTEL_TARGET/$TARGET_PROFILE_DIR/bundle/osx"
|
|
elif [[ "$TARGET_ARCH" == "$ARM_ARCH" ]]; then
|
|
echo "Building specifically for $ARM_TARGET"
|
|
DEFAULT_TARGET="$ARM_TARGET"
|
|
BUNDLE_DIR="target/$ARM_TARGET/$TARGET_PROFILE_DIR/bundle/osx"
|
|
fi
|
|
else
|
|
# Auto-detect default target based on current architecture
|
|
if [[ "$DEFAULT_ARCH" == *"$INTEL_ARCH"* ]]; then
|
|
echo "Default target is $INTEL_TARGET"
|
|
DEFAULT_TARGET="$INTEL_TARGET"
|
|
ADDITIONAL_TARGET="$ARM_TARGET"
|
|
BUNDLE_DIR="target/$INTEL_TARGET/$TARGET_PROFILE_DIR/bundle/osx"
|
|
elif [[ "$DEFAULT_ARCH" == *"$ARM_ARCH"* ]]; then
|
|
echo "Default target is $ARM_TARGET"
|
|
DEFAULT_TARGET="$ARM_TARGET"
|
|
ADDITIONAL_TARGET="$INTEL_TARGET"
|
|
BUNDLE_DIR="target/$ARM_TARGET/$TARGET_PROFILE_DIR/bundle/osx"
|
|
fi
|
|
fi
|
|
|
|
# Set artifact-specific configuration.
|
|
if [[ "$ARTIFACT" == cli ]]; then
|
|
UNIVERSAL_BINARY=false
|
|
OPEN_AFTER_BUNDLE=false
|
|
FEATURES="$FEATURES,standalone"
|
|
elif [[ "$ARTIFACT" == app ]]; then
|
|
FEATURES="$FEATURES,gui"
|
|
if [[ "$RELEASE_CHANNEL" == "local" || "$RELEASE_CHANNEL" == "dev" ]]; then
|
|
FEATURES="$FEATURES,nld_classifier_v2,nld_heuristic_v2"
|
|
else
|
|
FEATURES="$FEATURES,nld_classifier_v1,nld_heuristic_v1"
|
|
fi
|
|
fi
|
|
|
|
# If we're building a universal bundle for the app artifact, make sure the additional target is available.
|
|
if [[ $UNIVERSAL_BINARY = true ]]; then
|
|
rustup target add "$ADDITIONAL_TARGET"
|
|
fi
|
|
|
|
# If we only want to check that compilation will succeed, perform the checks
|
|
# then exit. We use this script to invoke `cargo check` to ensure that we are
|
|
# using the same feature flags and profile that we would be using in production.
|
|
if [[ "$CHECK_ONLY" == "true" ]]; then
|
|
cargo check --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --target "$DEFAULT_TARGET" --features "$FEATURES"
|
|
if [[ $UNIVERSAL_BINARY = true && "$ARTIFACT" != "cli" ]]; then
|
|
cargo check --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --target "$ADDITIONAL_TARGET" --features "$FEATURES"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
DMG_DIR="$BUNDLE_DIR/dmg/$WARP_BIN"
|
|
DMG_NAME="$WARP_APP_NAME.dmg"
|
|
if [[ -z "$FINAL_DMG_NAME" && -n "$DMG_NAME_SUFFIX" ]]; then
|
|
FINAL_DMG_NAME="$WARP_APP_NAME-$DMG_NAME_SUFFIX.dmg"
|
|
else
|
|
FINAL_DMG_NAME="$WARP_APP_NAME.dmg"
|
|
fi
|
|
|
|
# First clean up and prep the outdir
|
|
mkdir -p "$OUT_DIR"
|
|
rm -R "$OUT_DIR/$WARP_APP_NAME.app" || echo "No old app to remove"
|
|
rm -R "$OUT_DIR/$FINAL_DMG_NAME" || echo "No old dmg to remove"
|
|
|
|
###########################
|
|
## Step 1: Build the app ##
|
|
###########################
|
|
|
|
if [[ "$ARTIFACT" == "app" ]]; then
|
|
if [[ $BUILD_BINARY != true ]]; then
|
|
echo "Skipping binary build due to --skip-build flag"
|
|
export CARGO_BUNDLE_SKIP_BUILD=1
|
|
fi
|
|
|
|
pushd app > /dev/null
|
|
echo "Building and bundling $DEFAULT_TARGET for channel $RELEASE_CHANNEL and bundle id $BUNDLE_ID with profile $CARGO_PROFILE"
|
|
cargo bundle --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --target "$DEFAULT_TARGET" --features "$FEATURES"
|
|
popd > /dev/null
|
|
|
|
echo "Adding rpath to support mac frameworks (e.g. Sentry)"
|
|
install_name_tool -add_rpath "@executable_path/../Frameworks" "$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/MacOS/$WARP_BIN"
|
|
|
|
export WARP_SCHEME_NAME
|
|
export WARP_PLIST_PATH="$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/Info.plist"
|
|
./script/update_plist
|
|
|
|
if [[ $REGISTER_SERVICES = true ]]; then
|
|
plutil -insert NSServices -xml "
|
|
<array>
|
|
<dict>
|
|
<key>NSMenuItem</key>
|
|
<dict>
|
|
<key>default</key>
|
|
<string>New $WARP_APP_NAME Tab Here</string>
|
|
</dict>
|
|
<key>NSMessage</key>
|
|
<string>openTab</string>
|
|
<key>NSRequiredContext</key>
|
|
<dict>
|
|
<key>NSTextContent</key>
|
|
<string>FilePath</string>
|
|
</dict>
|
|
<key>NSSendTypes</key>
|
|
<array>
|
|
<string>NSFilenamesPboardType</string>
|
|
<string>public.plain-text</string>
|
|
</array>
|
|
</dict>
|
|
<dict>
|
|
<key>NSMenuItem</key>
|
|
<dict>
|
|
<key>default</key>
|
|
<string>New $WARP_APP_NAME Window Here</string>
|
|
</dict>
|
|
<key>NSMessage</key>
|
|
<string>openWindow</string>
|
|
<key>NSRequiredContext</key>
|
|
<dict>
|
|
<key>NSTextContent</key>
|
|
<string>FilePath</string>
|
|
</dict>
|
|
<key>NSSendTypes</key>
|
|
<array>
|
|
<string>NSFilenamesPboardType</string>
|
|
<string>public.plain-text</string>
|
|
</array>
|
|
</dict>
|
|
</array>" "$BUNDLE_DIR"/$WARP_APP_NAME.app/Contents/Info.plist
|
|
fi
|
|
|
|
# Temporary key that ChatGPT Desktop can use to determine if the latest version of Warp supports the ChatGPT integration.
|
|
# Once support has been rolled out for a sufficient amount of time we (and ChatGPT) can remove this.
|
|
plutil -insert SUPPORTS_CHAT_GPT_WORK_WITH_APPS -bool true "$BUNDLE_DIR"/$WARP_APP_NAME.app/Contents/Info.plist
|
|
|
|
# Add LSBackgroundOnly key and set it to false since we need a UI app
|
|
plutil -insert LSBackgroundOnly -bool false "$BUNDLE_DIR"/$WARP_APP_NAME.app/Contents/Info.plist
|
|
|
|
# Add SMAuthorizedClients for macOS 13+ (Ventura) to support login item functionality
|
|
plutil -insert SMAuthorizedClients -xml "<array><string>$BUNDLE_ID</string></array>" "$BUNDLE_DIR"/$WARP_APP_NAME.app/Contents/Info.plist
|
|
|
|
if [[ $UNIVERSAL_BINARY = true ]]; then
|
|
if [[ $BUILD_BINARY = true ]]; then
|
|
echo "Building $ADDITIONAL_TARGET to include in universal binary"
|
|
|
|
pushd app > /dev/null
|
|
cargo build --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --target "$ADDITIONAL_TARGET" --features "$FEATURES"
|
|
popd > /dev/null
|
|
else
|
|
echo "Skipping build of $ADDITIONAL_TARGET due to --skip-build flag"
|
|
fi
|
|
|
|
tmp_bundle_dir=$(mktemp -d -t ci-XXXXXXXXXX)
|
|
|
|
echo "Adding rpath to both binaries for universal executable"
|
|
install_name_tool -add_rpath "@executable_path/../Frameworks" "target/$INTEL_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN"
|
|
install_name_tool -add_rpath "@executable_path/../Frameworks" "target/$ARM_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN"
|
|
|
|
echo "Building universal binary using lipo."
|
|
lipo -create -output "$tmp_bundle_dir/$WARP_BIN" \
|
|
"target/$INTEL_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN" \
|
|
"target/$ARM_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN"
|
|
|
|
# Compute the real absolute path to the dSYM file, factoring in symlinks.
|
|
# Starting in Rust 1.56, the generated dSYMs are symlinks to files within the target/dep directory. For example,
|
|
# a dSYM for dev may be symlinked to target/deps/dev-080cf7e291fb066d.dSYM. This means the actual debug symbols are
|
|
# would be located at dev.dSYM/Contents/Resources/DWARF/dev-080cf7e291fb066d.dSYM where dev.dSYM is symlink to
|
|
# deps/dev-080cf7e291fb066d.dSYM. To fix this, parse out the actual name of the directory that the dSYM is
|
|
# symlinked to, since this is also the name of file that contains the debug symbols within the dSYM.
|
|
INTEL_DSYM_NAME=$(basename "$(realpath target/$INTEL_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM)" .dSYM)
|
|
INTEL_DSYM_PATH="target/$INTEL_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM/Contents/Resources/DWARF/$INTEL_DSYM_NAME"
|
|
ARM_DSYM_NAME=$(basename "$(realpath target/$ARM_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM)" .dSYM)
|
|
ARM_DSYM_PATH="target/$ARM_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM/Contents/Resources/DWARF/$ARM_DSYM_NAME"
|
|
if [[ -e "$INTEL_DSYM_PATH" && -e "$ARM_DSYM_PATH" ]]; then
|
|
echo "Building universal binary .dSYM using lipo and storing in $OUT_DIR/$WARP_BIN.dSYM"
|
|
|
|
# Use lipo to merge the .dSYM files into a single universal .dSYM file.
|
|
# It expects the base name for the file (with the .dSYM suffix removed).
|
|
lipo -create -output "$OUT_DIR/$WARP_BIN.dSYM" "${INTEL_DSYM_PATH}" "${ARM_DSYM_PATH}"
|
|
fi
|
|
|
|
echo "Storing result in $BUNDLE_DIR, replacing $DEFAULT_TARGET binary with fat binary."
|
|
mv "$tmp_bundle_dir/$WARP_BIN" "$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/MacOS"
|
|
elif [[ -n "$TARGET_ARCH" && -e "target/$DEFAULT_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM" ]]; then
|
|
echo "Copying .dSYM into $OUT_DIR/$WARP_BIN.dSYM"
|
|
cp -HR "target/$DEFAULT_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM" "$OUT_DIR/"
|
|
fi
|
|
|
|
# Note that the dock tile plugin is pre-built for both arm64 and x86_64 so we don't need to run lipo on it.
|
|
echo "Creating PlugIns directory and copying pre-built DockTilePlugin..."
|
|
mkdir -p "$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/PlugIns"
|
|
cp -R "$DOCK_TILE_PLUGIN_DIR" "$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/PlugIns/"
|
|
|
|
echo "Updating plist with dock tile plugin entries"
|
|
plutil -insert NSDockTilePlugIn -string "WarpDockTilePlugin.docktileplugin" "$BUNDLE_DIR"/$WARP_APP_NAME.app/Contents/Info.plist
|
|
plutil -insert MainAppBundleIdentifier -string "$BUNDLE_ID" "$BUNDLE_DIR"/$WARP_APP_NAME.app/Contents/PlugIns/WarpDockTilePlugin.docktileplugin/Contents/Info.plist
|
|
|
|
BUNDLED_RESOURCES_DIR="$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/Resources"
|
|
echo "Preparing bundled resources..."
|
|
"$WORKSPACE_ROOT_DIR/script/prepare_bundled_resources" "$BUNDLED_RESOURCES_DIR" "$RELEASE_CHANNEL" "$CARGO_PROFILE"
|
|
|
|
"$WORKSPACE_ROOT_DIR/script/compile_icon" "$RELEASE_CHANNEL" "$BUNDLE_DIR/$WARP_APP_NAME.app"
|
|
|
|
HELPERS_DIR="$BUNDLE_DIR/$WARP_APP_NAME.app/Contents/Helpers"
|
|
if [[ ",$FEATURES," =~ ",heap_usage_tracking," ]]; then
|
|
echo "Bundling pprof..."
|
|
"$WORKSPACE_ROOT_DIR/script/prepare_bundled_pprof" "$HELPERS_DIR"
|
|
fi
|
|
|
|
# Determine CLI wrapper script path based on release channel. Each channel's
|
|
# value here must match `Channel::cli_command_name` in the Rust source.
|
|
if [[ $RELEASE_CHANNEL = "stable" ]]; then
|
|
CLI_SCRIPT_PATH="$BUNDLED_RESOURCES_DIR/bin/oz"
|
|
elif [[ $RELEASE_CHANNEL = "oss" ]]; then
|
|
CLI_SCRIPT_PATH="$BUNDLED_RESOURCES_DIR/bin/warp-oss"
|
|
else
|
|
CLI_SCRIPT_PATH="$BUNDLED_RESOURCES_DIR/bin/oz-$RELEASE_CHANNEL"
|
|
fi
|
|
|
|
echo "Creating Resources/bin directory and CLI wrapper script..."
|
|
mkdir -p "$BUNDLED_RESOURCES_DIR/bin"
|
|
|
|
cat > "$CLI_SCRIPT_PATH" << 'EOF'
|
|
#!/bin/bash
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
exec -a "$0" "$script_dir/../../MacOS/WARP_BIN_PLACEHOLDER" "$@"
|
|
EOF
|
|
|
|
# Replace the placeholder with the actual binary name
|
|
sed -i '' "s/WARP_BIN_PLACEHOLDER/$WARP_BIN/" "$CLI_SCRIPT_PATH"
|
|
|
|
# Make the script executable
|
|
chmod +x "$CLI_SCRIPT_PATH"
|
|
|
|
# Store the built artifact locations for GitHub Actions outputs.
|
|
BINARY_PATH="target/$DEFAULT_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN"
|
|
DMG_PATH="$OUT_DIR/$FINAL_DMG_NAME"
|
|
elif [[ "$ARTIFACT" == "cli" ]]; then
|
|
if [[ $BUILD_BINARY == true ]]; then
|
|
# Create Info.plist before building the app, since it's embedded at build time.
|
|
# Apple's codesigning tools will detect Info.plist files in the same directory as an executable.
|
|
# This breaks the code signature, so we must use a different location for the file.
|
|
mkdir -p "$BUNDLE_DIR"
|
|
export WARP_PLIST_PATH="$BUNDLE_DIR/cli-info.plist"
|
|
cp app/assets/resources/mac/CLI-Info.plist "$WARP_PLIST_PATH"
|
|
|
|
export WARP_PLIST_NO_FILE_TYPES=true
|
|
./script/update_plist
|
|
plutil -insert CFBundleIdentifier -string "$BUNDLE_ID" "$WARP_PLIST_PATH"
|
|
plutil -insert CFBundleName -string "$WARP_BIN" "$WARP_PLIST_PATH"
|
|
plutil -insert CFBundleExecutable -string "$WARP_BIN" "$WARP_PLIST_PATH"
|
|
|
|
export "INFO_PLIST_PATH=$(realpath "$WARP_PLIST_PATH")"
|
|
pushd app > /dev/null
|
|
echo "Building $DEFAULT_TARGET for channel $RELEASE_CHANNEL with profile $CARGO_PROFILE"
|
|
cargo build --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --target "$DEFAULT_TARGET" --features "$FEATURES"
|
|
popd > /dev/null
|
|
else
|
|
echo "Skipping binary build due to --skip-build flag"
|
|
fi
|
|
|
|
echo "Copying binary into $OUT_DIR/$WARP_BIN"
|
|
cp "target/$DEFAULT_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN" "$OUT_DIR/$WARP_BIN"
|
|
|
|
if [[ -n "$TARGET_ARCH" && -e "target/$DEFAULT_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM" ]]; then
|
|
echo "Copying .dSYM into $OUT_DIR/$WARP_BIN.dSYM"
|
|
cp -HR "target/$DEFAULT_TARGET/$TARGET_PROFILE_DIR/$WARP_BIN.dSYM" "$OUT_DIR/"
|
|
fi
|
|
|
|
echo "Preparing CLI resources directory"
|
|
BUNDLED_RESOURCES_DIR="$OUT_DIR/resources"
|
|
"$WORKSPACE_ROOT_DIR/script/prepare_bundled_resources" "$BUNDLED_RESOURCES_DIR" "$RELEASE_CHANNEL" "$CARGO_PROFILE"
|
|
|
|
|
|
# Set the primary binary path to output.
|
|
BINARY_PATH="$OUT_DIR/$WARP_BIN"
|
|
else
|
|
echo "Unsupported artifact: $ARTIFACT" >&2
|
|
exit 1
|
|
fi
|
|
|
|
##########################################
|
|
## Step 2: Create code-signing keychain ##
|
|
##########################################
|
|
|
|
if [[ $READ_PASSWORDS_FROM_ENV != true ]]; then
|
|
echo "Skipping code-signing because passwords are not available in environment."
|
|
CODESIGN=false
|
|
fi
|
|
|
|
if [[ $CODESIGN = true ]]; then
|
|
# TODO - does this need to change per user? Seems like it's tied to the WARP_NOTARIZATION_PASSWORD password.
|
|
APPLE_TEAM_ID="2BBY89MBSN"
|
|
CODESIGN_KEYCHAIN_NAME="warp-codesign-keychain"
|
|
|
|
echo "Starting codesigning..."
|
|
|
|
if [[ $READ_PASSWORDS_FROM_ENV = true ]]; then
|
|
if [ -z "$WARP_NOTARIZATION_PASSWORD" ] ; then
|
|
echo "WARP_NOTARIZATION_PASSWORD must be set for code signing"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$WARP_DEVELOPER_ID_CERT_PASSWORD" ] ; then
|
|
echo "WARP_DEVELOPER_ID_CERT_PASSWORD must be set for code signing"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$WARP_CODESIGN_KEYCHAIN_PASSWORD" ] ; then
|
|
echo "WARP_CODESIGN_KEYCHAIN_PASSWORD must be set for code signing"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
security delete-keychain $CODESIGN_KEYCHAIN_NAME || echo "No existing keychain to clean up".
|
|
|
|
echo "Creating $CODESIGN_KEYCHAIN_NAME keychain."
|
|
security create-keychain -p "$WARP_CODESIGN_KEYCHAIN_PASSWORD" $CODESIGN_KEYCHAIN_NAME
|
|
security list-keychains -s $CODESIGN_KEYCHAIN_NAME
|
|
security set-keychain-settings -t 3600 -u $CODESIGN_KEYCHAIN_NAME
|
|
|
|
echo "Unlocking keychain and setting cert."
|
|
security unlock-keychain -p "$WARP_CODESIGN_KEYCHAIN_PASSWORD" $CODESIGN_KEYCHAIN_NAME
|
|
security import <(echo "$WARP_DEVELOPER_ID_CERT" | base64 -d) -f pkcs12 -P "$WARP_DEVELOPER_ID_CERT_PASSWORD" -k $CODESIGN_KEYCHAIN_NAME -T /usr/bin/codesign
|
|
security set-key-partition-list -S "apple-tool:,apple:" -s -k "$WARP_CODESIGN_KEYCHAIN_PASSWORD" $CODESIGN_KEYCHAIN_NAME
|
|
fi
|
|
|
|
##############################
|
|
## Step 3: Codesign the app ##
|
|
##############################
|
|
|
|
if [[ $SELFSIGN = true ]]; then
|
|
SIGNING_CERT="$(security find-identity -p codesigning -v | grep "Apple Development" | awk '{print $2}' | head -1)"
|
|
if [[ -z "$SIGNING_CERT" ]]; then
|
|
echo "No Apple Development cert found, falling back to ad-hoc signing."
|
|
SIGNING_CERT="-"
|
|
else
|
|
echo "Found Apple Development certificate"
|
|
fi
|
|
if [[ "$ARTIFACT" == app ]]; then
|
|
echo "Self-signing $BUNDLE_DIR/$WARP_APP_NAME.app with ${SIGNING_CERT}..."
|
|
codesign --force --deep --options runtime --sign "$SIGNING_CERT" "$BUNDLE_DIR/$WARP_APP_NAME.app" --entitlements script/Debug-Entitlements.plist
|
|
elif [[ "$ARTIFACT" == cli ]]; then
|
|
echo "Self-signing $OUT_DIR/$WARP_BIN with ${SIGNING_CERT}..."
|
|
codesign --force --options runtime --sign "$SIGNING_CERT" "$OUT_DIR/$WARP_BIN" --entitlements script/Debug-Entitlements.plist
|
|
fi
|
|
elif [[ $CODESIGN = true ]]; then
|
|
if [[ "$ARTIFACT" == app ]]; then
|
|
echo "Codesigning $BUNDLE_DIR/$WARP_APP_NAME.app..."
|
|
# Use --deep so we sign bundled frameworks as well
|
|
codesign --deep -f -o runtime --timestamp -s "$APPLE_TEAM_ID" "$BUNDLE_DIR/$WARP_APP_NAME.app" --entitlements script/Entitlements.plist
|
|
elif [[ "$ARTIFACT" == cli ]]; then
|
|
echo "Codesigning $OUT_DIR/$WARP_BIN..."
|
|
codesign -f -o runtime --timestamp -s "$APPLE_TEAM_ID" "$OUT_DIR/$WARP_BIN" --entitlements script/Entitlements.plist
|
|
|
|
# Create the .zip for notarization in a separate location - otherwise, Apple's codesigning
|
|
# tools decide that it's a sealed resource that belongs to the binary and needs to also be signed.
|
|
NOTARIZATION_ARTIFACT="$BUNDLE_DIR/${WARP_BIN}_notarize.zip"
|
|
if [[ -e "$NOTARIZATION_ARTIFACT" ]]; then
|
|
echo "Removing old notarization artifact..."
|
|
rm "$NOTARIZATION_ARTIFACT"
|
|
fi
|
|
|
|
# Create a .zip archive to notarize.
|
|
ditto -c -k "$OUT_DIR/$WARP_BIN" "$NOTARIZATION_ARTIFACT"
|
|
|
|
# It's not possible to staple notarization tickets to standalone binaries:
|
|
# https://developer.apple.com/documentation/security/customizing-the-notarization-workflow?language=objc#Staple-the-ticket-to-your-distribution
|
|
STAPLE_TICKET=false
|
|
fi
|
|
fi
|
|
|
|
########################
|
|
## Step 4: Create DMG ##
|
|
########################
|
|
|
|
if [[ "$ARTIFACT" = app ]]; then
|
|
function create_warp_dmg() {
|
|
echo "Creating $DMG_DIR/$DMG_NAME..."
|
|
rm "$DMG_DIR/$DMG_NAME" || true
|
|
local source_folder="$1"
|
|
|
|
local args=(
|
|
--volname Warp
|
|
# For --no-internet-enable, see https://github.com/create-dmg/create-dmg/issues/179
|
|
--no-internet-enable
|
|
--background app/assets/resources/mac/warp_install_image.png
|
|
--icon-size 128
|
|
--window-size 700 500
|
|
--format UDZO
|
|
--app-drop-link 550 250
|
|
--icon "$WARP_APP_NAME.app" 150 250
|
|
# macOS 26.4 Beta has issues with mounting HFS+ DMGs, so we're using APFS instead.
|
|
# APFS has been supported as a DMG filesystem since macOS 10.13, and we target 10.14
|
|
# as our minimum version.
|
|
#
|
|
# See: https://developer.apple.com/documentation/macos-release-notes/macos-26_4-release-notes#External-Media
|
|
--filesystem APFS
|
|
)
|
|
|
|
# Skip running an AppleScript to format the DMG contents if running in Namespace - this consistently times out.
|
|
# See https://github.com/create-dmg/create-dmg/issues/72
|
|
if [[ "${RUNNER_NAME:-}" == nsc-* ]]; then
|
|
args+=(--skip-jenkins)
|
|
fi
|
|
|
|
args+=("$DMG_DIR/$DMG_NAME" "$source_folder")
|
|
|
|
create-dmg "${args[@]}"
|
|
}
|
|
|
|
# If we're codesigning, stage the signed app and use that to create the DMG.
|
|
# Otherwise, create a DMG from the bundle dir directly.
|
|
if [[ $CODESIGN = true ]]; then
|
|
if test -d "$DMG_DIR"; then
|
|
echo "Clearing old dmg directory $DMG_DIR"
|
|
rm -r "$DMG_DIR"
|
|
fi
|
|
echo "Creating $DMG_DIR"
|
|
mkdir -p "$DMG_DIR"
|
|
cp -R "$BUNDLE_DIR/$WARP_APP_NAME.app" "$DMG_DIR"
|
|
|
|
create_warp_dmg "$DMG_DIR"
|
|
|
|
echo "Codesigning $DMG_DIR/$DMG_NAME..."
|
|
codesign -s "$APPLE_TEAM_ID" --timestamp "$DMG_DIR/$DMG_NAME"
|
|
|
|
NOTARIZATION_ARTIFACT="$DMG_DIR/$DMG_NAME"
|
|
STAPLE_TICKET=true
|
|
else
|
|
echo "Creating $DMG_DIR"
|
|
mkdir -p "$DMG_DIR"
|
|
|
|
echo "Cleaning up any existing DMG files before creating new ones..."
|
|
cleanup_dmg_files "$DMG_DIR"
|
|
|
|
create_warp_dmg "$BUNDLE_DIR"
|
|
fi
|
|
fi
|
|
|
|
##############################
|
|
## Step 5: Notarize the app ##
|
|
##############################
|
|
|
|
if [[ $CODESIGN = true ]]; then
|
|
echo "Uploading $NOTARIZATION_ARTIFACT to Apple for notarization..."
|
|
xcrun notarytool submit "$NOTARIZATION_ARTIFACT" --apple-id "$WARP_NOTARIZATION_APPLE_ID" --password "$WARP_NOTARIZATION_PASSWORD" --team-id "$APPLE_TEAM_ID" --wait
|
|
|
|
if [[ $STAPLE_TICKET = true ]]; then
|
|
echo "Attempting to staple the notarization ticket to $NOTARIZATION_ARTIFACT..."
|
|
xcrun stapler staple "$NOTARIZATION_ARTIFACT"
|
|
fi
|
|
|
|
if [[ $? != 0 ]]; then
|
|
echo "Notarization failed; see above output for details."
|
|
exit 1
|
|
fi
|
|
|
|
# Verify the notarization results (this is format-dependent)
|
|
echo "Verifying notarization ticket..."
|
|
if [[ "$ARTIFACT" = app ]]; then
|
|
xcrun stapler validate "$DMG_DIR/$DMG_NAME"
|
|
elif [[ "$ARTIFACT" = cli ]]; then
|
|
spctl -a -t open --context context:primary-signature -vv "$OUT_DIR/$WARP_BIN"
|
|
fi
|
|
fi
|
|
|
|
|
|
#######################################
|
|
## Step 6: Copy and output artifacts ##
|
|
#######################################
|
|
|
|
if [[ "$ARTIFACT" = app ]]; then
|
|
echo "Copying dmg and app to $OUT_DIR"
|
|
cp -R "$BUNDLE_DIR/$WARP_APP_NAME.app" "$OUT_DIR"
|
|
cp "$DMG_DIR/$DMG_NAME" "$OUT_DIR/$FINAL_DMG_NAME"
|
|
fi
|
|
|
|
# If this is being run within a GitHub action, set an output variable with the
|
|
# location of the artifacts so they can be referenced by subsequent actions.
|
|
if [ "${GITHUB_ACTIONS}" == "true" ]; then
|
|
echo "::echo::on"
|
|
|
|
# For individual architecture builds, output binary information
|
|
if [[ -n "$TARGET_ARCH" ]]; then
|
|
echo "binary_path=$BINARY_PATH" >> "$GITHUB_OUTPUT"
|
|
echo "target_arch=$TARGET_ARCH" >> "$GITHUB_OUTPUT"
|
|
echo "rust_target=$DEFAULT_TARGET" >> "$GITHUB_OUTPUT"
|
|
|
|
# If the dSYM is available, output both its path and its realpath.
|
|
# The realpath is needed because the dSYM is a symlink, and when preserving
|
|
# the build artifacts, we want to preserve both the symlink and its target.
|
|
DSYM_PATH="${BINARY_PATH}.dSYM"
|
|
if [[ -d "$DSYM_PATH" ]]; then
|
|
echo "dsym_path=$DSYM_PATH" >> "$GITHUB_OUTPUT"
|
|
|
|
# If the dSYM is a symlink, output its real path.
|
|
if [[ -L "$DSYM_PATH" ]]; then
|
|
echo "dsym_realpath=$(relpath $(realpath $DSYM_PATH))" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo "dock_tile_plugin_dir=$DOCK_TILE_PLUGIN_DIR" >> "$GITHUB_OUTPUT"
|
|
echo "frameworks_dir=app/frameworks/${FRAMEWORK_OVERRIDE:-default}" >> "$GITHUB_OUTPUT"
|
|
|
|
# For full bundles, output DMG information
|
|
if [[ -f "$OUT_DIR/$FINAL_DMG_NAME" ]]; then
|
|
echo "dmg_name=$FINAL_DMG_NAME" >> "$GITHUB_OUTPUT"
|
|
echo "dmg_path=$DMG_PATH" >> "$GITHUB_OUTPUT"
|
|
echo "dsym_folder_path=$OUT_DIR" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
if [[ -n "$BUNDLED_RESOURCES_DIR" ]]; then
|
|
echo "bundled_resources_dir=$BUNDLED_RESOURCES_DIR" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
echo "::echo::off"
|
|
fi
|
|
|
|
if [[ $OPEN_AFTER_BUNDLE = true ]]; then
|
|
open "$OUT_DIR"
|
|
fi
|