Initial public release of Warp.

Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
This commit is contained in:
David Stern
2026-04-28 08:43:33 -05:00
commit 0dbd3d567a
4982 changed files with 1431549 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -e
# Update the apt cache before installing dependencies. It can be slow, so the install scripts
# don't do it (to avoid doing it more than once).
sudo apt update -y
# Install all dependencies needed to build, run, and test Warp.
"$PWD"/script/linux/install_test_deps
# Install linuxdeploy.
"$PWD"/script/linux/install_linuxdeploy
# Make sure we're authenticated with the gcloud CLI, otherwise SSH integration
# tests won't work.
if [[ -z "$(gcloud auth print-identity-token)" ]]; then
echo "gcloud CLI authentication missing. Press enter to continue..."
read var
gcloud auth login
fi
echo "✅ Your machine is bootstrapped and ready to go. :)"
+277
View File
@@ -0,0 +1,277 @@
#!/usr/bin/env bash
#
# Builds a Warp binary and bundles it up for distribution.
set -e
WORKSPACE_ROOT_DIR="$(pwd)"
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORKSPACE_ROOT_DIR/target}"
DIST_DIR="$CARGO_TARGET_DIR/dist"
cleanup() {
# Delete the directory that was used as a staging area during the bundling
# process.
if [ -d "$DIST_DIR" ]; then
rm -rf "$DIST_DIR"
fi
}
# Run cleanup() when the script terminates (whether it succeeded or failed).
trap cleanup EXIT
# By default we build dev bundles.
RELEASE_CHANNEL="dev"
FEATURES="release_bundle,crash_reporting"
PACKAGES=( appimage )
BUILD="true"
BUILD_ARCH="$(uname -m)"
DEBUG=false
ARTIFACT="app"
# Cache all params so we can pass them to downstream scripts.
ALL_PARAMS=$@
PARAMS=""
while (( "$#" )); do
case "$1" in
--debug)
DEBUG=true
shift
;;
--check-only)
echo 'Only running `cargo check` and not producing a bundle.'
CHECK_ONLY="true"
shift
;;
--skip-build)
BUILD="false"
shift
;;
--nouniversal)
# Discard the --nouniversal argument, which is only used for macOS
# bundles.
shift
;;
-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
;;
--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
;;
--packages)
PACKAGES=( $(IFS=, ; echo $2) )
shift 2
;;
--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
;;
--arch)
if [ -n "$2" ]; then
if [ "$2" = "aarch64" -o "$2" = "x86_64" ]; then
echo "Setting architecture to $2"
export BUILD_ARCH=$2
shift 2
else
echo "Error: Argument for $1 is invalid; got '$2' but expected 'aarch64' or 'x86_64'." >&2
exit 1
fi
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"
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).
CARGO_PROFILE="release-lto-debug_assertions"
else
CARGO_PROFILE="release-lto"
fi
if [[ "$CARGO_PROFILE" == "dev" ]]; then
CARGO_TARGET_OUTPUT_DIR="$CARGO_TARGET_DIR/debug"
else
CARGO_TARGET_OUTPUT_DIR="$CARGO_TARGET_DIR/$CARGO_PROFILE"
fi
# NOTE: if you change this path, update the "Clean stale bundle output"
# steps in .github/workflows/create_release.yml so they continue to wipe
# stale packages left in the shared Namespace runner cache.
OUT_DIR="$CARGO_TARGET_OUTPUT_DIR/bundle/linux"
mkdir -p "$OUT_DIR"
# Update parameters based on the target release channel.
#
# APP_NAME here must match the value used in Rust as the
# application name; see app/src/channel.rs.
#
# WARP_BIN is the name of the binary produced by cargo;
# BINARY_NAME is the desired name of the binary in the final package.
if [[ $RELEASE_CHANNEL = "local" ]]; then
WARP_BIN="warp"
BINARY_NAME="warp-local"
APP_NAME="WarpLocal"
FEATURES="$FEATURES,agent_mode_debug"
export HANDLE_MARKDOWN=1
elif [[ $RELEASE_CHANNEL = "dev" ]]; then
WARP_BIN="dev"
BINARY_NAME="warp-dev"
APP_NAME="WarpDev"
FEATURES="$FEATURES,agent_mode_debug"
# Enable heap profiling using jemalloc through pprof.
FEATURES="$FEATURES,jemalloc_pprof"
export HANDLE_MARKDOWN=1
elif [[ $RELEASE_CHANNEL = "preview" ]]; then
WARP_BIN="preview"
BINARY_NAME="warp-preview"
APP_NAME="WarpPreview"
FEATURES="$FEATURES,preview_channel"
elif [[ $RELEASE_CHANNEL = "stable" ]]; then
WARP_BIN="stable"
BINARY_NAME="warp"
APP_NAME="Warp"
fi
# Artifact-specific binary naming
if [[ "$ARTIFACT" == "cli" ]]; then
# For CLI artifacts, use oz instead of warp as the binary name
BINARY_NAME="${BINARY_NAME/warp/oz}"
fi
# Artifact-specific configuration
if [[ "$ARTIFACT" == "cli" ]]; then
FEATURES="$FEATURES,standalone"
elif [[ "$ARTIFACT" == "app" ]]; then
FEATURES="$FEATURES,gui,nld_improvements"
fi
BUNDLE_ID="dev.warp.$APP_NAME"
EXECUTABLE_PATH="$CARGO_TARGET_OUTPUT_DIR/$WARP_BIN"
DEBUG_EXECUTABLE_PATH="$EXECUTABLE_PATH.debug"
# Note that this variable must be set (and exported!) before we compile the
# binary, as it is read at compile time by Linux autoupdate logic (to know the
# expected name of the AppImage when downloading updates).
export APPIMAGE_NAME="$APP_NAME-$BUILD_ARCH.AppImage"
# 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 -p warp --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --features "$FEATURES"
exit 0
fi
# Build the binary.
if [[ "$BUILD" == "true" ]]; then
echo "Building and bundling Warp for channel $RELEASE_CHANNEL and bundle id $BUNDLE_ID"
cargo build -p warp --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --features "$FEATURES"
echo "Making debug copy of '$EXECUTABLE_PATH' at '$DEBUG_EXECUTABLE_PATH'"
cp "$EXECUTABLE_PATH" "$DEBUG_EXECUTABLE_PATH"
echo "Stripping debug symbols from '$EXECUTABLE_PATH'"
if [[ $RELEASE_CHANNEL = "dev" ]]; then
# For dev builds, only strip debug symbols, as we want to keep some
# symbols for profiling purposes.
strip --strip-debug "$EXECUTABLE_PATH"
else
# For production builds, strip all symbols, to keep the binary size
# smaller.
strip --strip-all "$EXECUTABLE_PATH"
fi
else
echo 'Skipping `cargo build` step due to --skip-build argument'
fi
# Prepare bundled resources for CLI builds.
if [[ "$ARTIFACT" == "cli" ]]; then
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"
fi
# If this is being run within a GitHub action, set an output variable with the
# location of the binary so it can be referenced by subsequent actions, as well
# as the directory containing all built packages.
if [ "${GITHUB_ACTIONS}" == "true" ]; then
echo "::echo::on"
echo "executable_path=$EXECUTABLE_PATH" >> "$GITHUB_OUTPUT"
echo "debug_executable_path=$DEBUG_EXECUTABLE_PATH" >> "$GITHUB_OUTPUT"
echo "packages_dir=$OUT_DIR" >> "$GITHUB_OUTPUT"
echo "bundled_resources_dir=${BUNDLED_RESOURCES_DIR:-}" >> "$GITHUB_OUTPUT"
echo "::echo::off"
fi
# Make sure a variety of environment variables are available in downstream scripts.
export \
WORKSPACE_ROOT_DIR \
DIST_DIR \
CARGO_TARGET_OUTPUT_DIR \
OUT_DIR \
RELEASE_CHANNEL \
BUNDLE_ID \
EXECUTABLE_PATH \
BINARY_NAME \
APPIMAGE_NAME \
BUILD_ARCH \
ARTIFACT \
CARGO_PROFILE
# Build the AppImage bundle.
if [[ ${PACKAGES[@]} =~ "appimage" ]]; then
echo "Building AppImage..."
"$WORKSPACE_ROOT_DIR/script/linux/bundle_appimage"
fi
# Build the .deb package.
if [[ ${PACKAGES[@]} =~ "deb" ]]; then
echo "Building .deb package..."
"$WORKSPACE_ROOT_DIR/script/linux/bundle_deb"
fi
# Build the .rpm package.
if [[ ${PACKAGES[@]} =~ "rpm" ]]; then
echo "Building .rpm package..."
"$WORKSPACE_ROOT_DIR/script/linux/bundle_rpm"
fi
# Build the Arch Linux package.
if [[ ${PACKAGES[@]} =~ "arch" ]]; then
echo "Building Arch Linux package..."
"$WORKSPACE_ROOT_DIR/script/linux/bundle_arch"
fi
+98
View File
@@ -0,0 +1,98 @@
#!/usr/bin/env bash
#
# Builds an AppImage as part of the bundling process.
#
# Required environment variables:
# - WORKSPACE_ROOT_DIR: The root directory of the Cargo workspace.
# - DIST_DIR: A temporary directory we can use for staging files as we build the package.
# - OUT_DIR: The directory into which we should place the final package.
# - CARGO_TARGET_OUTPUT_DIR: The cargo target directory containing build output.
# - RELEASE_CHANNEL: The release channel we're bundling (e.g.: "dev").
# - BUNDLE_ID: The app ID for the bundle (e.g.: "dev.warp.WarpDev").
# - EXECUTABLE_PATH: The path to the compiled executable we want to install.
# - BINARY_NAME: The name that the compiled executable should have on the target machine.
# - APPIMAGE_NAME: The name of the AppImage file to produce.
STAGE_DIR="$DIST_DIR/appimagepkg"
APP_DIR="$DIST_DIR/AppDir"
# Extract channel suffix from BINARY_NAME
if [ "$ARTIFACT" = "cli" ]; then
CHANNEL_SUFFIX="${BINARY_NAME#oz}"
else
CHANNEL_SUFFIX="${BINARY_NAME#warp}"
fi
PACKAGE_NAME="warp-terminal$CHANNEL_SUFFIX"
# Adding NO_STRIP to stop linuxdeploy from attempting to strip symbols
# from binaries built on a different arch than the current symbol.
BUILD_ARCH="${BUILD_ARCH:-$(uname -m)}"
if [ "$BUILD_ARCH" != "$(uname -m)" ]; then
export NO_STRIP=1
fi
cleanup() {
# Delete the directories used as staging areas during the bundling
# process.
if [ -d "$STAGE_DIR" ]; then
rm -rf "$STAGE_DIR"
fi
if [ -d "$APP_DIR" ]; then
rm -rf "$APP_DIR"
fi
}
# Run cleanup() when the script terminates (whether it succeeded or failed).
trap cleanup EXIT
# Construct a directory to contain the staged package contents.
rm -rf "$STAGE_DIR"
mkdir -p "$STAGE_DIR"
# Populate the directory with the package contents, in the appropriate
# locations.
OPT_DIR="/opt/warpdotdev/$PACKAGE_NAME"
source "$WORKSPACE_ROOT_DIR/script/linux/bundle_install" "$STAGE_DIR"
# Modify the "Exec=" line in the .desktop file to use the name of the installed
# binary and not our /usr/bin symlink (which doesn't exist in an AppImage).
sed -i -E 's/Exec=warp-terminal/Exec=warp/' "$STAGE_DIR/usr/share/applications/$BUNDLE_ID.desktop"
# Find all icon files from inside the package staging directory.
ICON_FILES=( $(find "$STAGE_DIR/usr/share/icons" -name "*.png") )
# Make sure there's no lingering AppDir from a previous execution.
rm -rf "$APP_DIR"
# Run linuxdeploy to create an appropriately-structured AppDir and turn it into
# an AppImage, located in OUT_DIR.
#
# We use a custom input plugin (bundled-resources) to copy Warp's bundled
# resources into the AppDir alongside the executable, since linuxdeploy only
# deploys the binary, desktop file, and icons by default.
cd "$OUT_DIR"
echo "Running linuxdeploy to create the AppImage"
export WARP_BINARY_NAME="$BINARY_NAME"
export WARP_PACKAGE_NAME="$PACKAGE_NAME"
export WARP_BUNDLED_RESOURCES_DIR="${STAGE_DIR}${OPT_DIR}/resources"
export PATH="$WORKSPACE_ROOT_DIR/script/linux:$PATH"
linuxdeploy \
--appdir "$APP_DIR" \
--executable "${STAGE_DIR}${OPT_DIR}/$BINARY_NAME" \
--desktop-file "$STAGE_DIR/usr/share/applications/$BUNDLE_ID.desktop" \
$(for i in "${ICON_FILES[@]}"; do echo "--icon-file $i "; done) \
--plugin warp \
--output appimage
APPIMAGE_PATH="$OUT_DIR/$APPIMAGE_NAME"
# If this is being run within a GitHub action, set an output variable with the
# location of the AppImage so it can be referenced by subsequent actions.
if [ "${GITHUB_ACTIONS}" == "true" ]; then
echo "::echo::on"
echo "appimage_path=$APPIMAGE_PATH" >> "$GITHUB_OUTPUT"
echo "::echo::off"
fi
echo "Successfully built AppImage at $APPIMAGE_PATH!"
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
#
# Builds an Arch Linux package as part of the bundling process.
#
# Required environment variables:
# - WORKSPACE_ROOT_DIR: The root directory of the Cargo workspace.
# - DIST_DIR: A temporary directory we can use for staging files as we build the package.
# - OUT_DIR: The directory into which we should place the final package.
# - CARGO_TARGET_OUTPUT_DIR: The cargo target directory containing build output.
# - RELEASE_CHANNEL: The release channel we're bundling (e.g.: "dev").
# - BUNDLE_ID: The app ID for the bundle (e.g.: "dev.warp.WarpDev").
# - EXECUTABLE_PATH: The path to the compiled executable we want to install.
# - BINARY_NAME: The name that the compiled executable should have on the target machine.
# - ARTIFACT: Which artifact to build: app or cli.
set -e
# Extract channel suffix from BINARY_NAME
if [ "$ARTIFACT" = "cli" ]; then
CHANNEL_SUFFIX="${BINARY_NAME#oz}"
else
CHANNEL_SUFFIX="${BINARY_NAME#warp}"
fi
# On Linux, we keep the `-stable` suffix for stable to avoid package conflicts.
# The binary name is still `oz`, and the repo name is still `warpdotdev`.
if [ "$ARTIFACT" = "cli" -a "$RELEASE_CHANNEL" = "stable" ]; then
CHANNEL_SUFFIX="-stable"
fi
if [ "$ARTIFACT" = "app" ]; then
PACKAGE_NAME="warp-terminal$CHANNEL_SUFFIX"
elif [ "$ARTIFACT" = "cli" ]; then
PACKAGE_NAME="oz$CHANNEL_SUFFIX"
else
echo "::error ::Unknown ARTIFACT: $ARTIFACT (expected 'app' or 'cli')"
exit 1
fi
BUILD_ARCH="${BUILD_ARCH:-$(uname -m)}"
if [ "$BUILD_ARCH" = "aarch64" ]; then
ARCH="aarch64"
else
ARCH="x86_64"
fi
PKGDIR="$DIST_DIR/archpkg"
cleanup() {
# Delete the AppDir that was used as a staging area during the bundling
# process.
if [ -d "$PKGDIR" ]; then
rm -rf "$PKGDIR"
fi
}
# Run cleanup() when the script terminates (whether it succeeded or failed).
trap cleanup EXIT
# Construct a directory that contains all of the output data.
rm -rf "$PKGDIR"
mkdir -p "$PKGDIR"
# Bundle the base filesystem into an archive to be unpacked by makepkg.
mkdir "$PKGDIR/stage"
OPT_DIR="/opt/warpdotdev/$PACKAGE_NAME"
source "$WORKSPACE_ROOT_DIR/script/linux/bundle_install" "$PKGDIR/stage"
tar cvf "$PKGDIR/data.tar" -C "$PKGDIR/stage" .
# Move the Arch-specific package metadata into the package directory.
VERSION="$GIT_RELEASE_TAG"
RELEASE=1
sed \
"s#@@CHANNEL_SUFFIX@@#$CHANNEL_SUFFIX#g; s#@@VERSION@@#$VERSION#g; s#@@RELEASE@@#$RELEASE#g; s#@@ARCH@@#$ARCH#g; s#@@OUTDIR@@#$OUT_DIR#g; s#@@BINARY_NAME@@#$BINARY_NAME#g" \
< "$WORKSPACE_ROOT_DIR/resources/linux/arch/$ARTIFACT/PKGBUILD.template" \
> "$PKGDIR/PKGBUILD"
# Only create wrapper script for app artifact
if [ "$ARTIFACT" = "app" ]; then
sed \
"s#@@CHANNEL_SUFFIX@@#$CHANNEL_SUFFIX#g; s#@@BINARY_NAME@@#$BINARY_NAME#g" \
< "$WORKSPACE_ROOT_DIR/resources/linux/arch/$ARTIFACT/warp.sh.template" \
> "$PKGDIR/$PACKAGE_NAME.sh"
fi
# Build the actual package.
#
# We install any needed build and runtime dependencies before making the
# package, and remove them again afterwards. We also skip verifying
# checksums for the source files, as we generate them above and there's not
# much reason to generate the checksums and then verify them immediately
# afterwards.
if [ "${GITHUB_ACTIONS}" == "true" ]; then
# If we're running in a GitHub action, don't ask for confirmation before
# installing packages.
EXTRA_ARGS="--noconfirm"
fi
cd "$PKGDIR"
PKGDEST="$OUT_DIR" CARCH="$ARCH" makepkg -cfrs --needed --skipchecksums "$EXTRA_ARGS"
PACKAGE_PATH="$OUT_DIR/${PACKAGE_NAME}-${VERSION}-${RELEASE}-${ARCH}.pkg.tar.zst"
echo "Successfully built Arch package at $PACKAGE_PATH!"
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env bash
#
# Builds a .deb package as part of the bundling process.
#
# Required environment variables:
# - WORKSPACE_ROOT_DIR: The root directory of the Cargo workspace.
# - DIST_DIR: A temporary directory we can use for staging files as we build the package.
# - OUT_DIR: The directory into which we should place the final package.
# - CARGO_TARGET_OUTPUT_DIR: The cargo target directory containing build output.
# - RELEASE_CHANNEL: The release channel we're bundling (e.g.: "dev").
# - BUNDLE_ID: The app ID for the bundle (e.g.: "dev.warp.WarpDev").
# - EXECUTABLE_PATH: The path to the compiled executable we want to install.
# - BINARY_NAME: The name that the compiled executable should have on the target machine.
# - ARTIFACT: Which artifact to build: app or cli.
set -e
# Extract channel suffix from BINARY_NAME
if [ "$ARTIFACT" = "cli" ]; then
CHANNEL_SUFFIX="${BINARY_NAME#oz}"
else
CHANNEL_SUFFIX="${BINARY_NAME#warp}"
fi
REPO_NAME="warpdotdev$CHANNEL_SUFFIX"
# On Linux, we keep the `-stable` suffix for stable to avoid package conflicts.
# The binary name is still `oz`, and the repo name is still `warpdotdev`.
if [ "$ARTIFACT" = "cli" -a "$RELEASE_CHANNEL" = "stable" ]; then
CHANNEL_SUFFIX="-stable"
fi
case "$ARTIFACT" in
app)
PACKAGE_NAME="warp-terminal$CHANNEL_SUFFIX"
;;
cli)
PACKAGE_NAME="oz$CHANNEL_SUFFIX"
;;
*)
echo "::error ::Unknown ARTIFACT: $ARTIFACT (expected 'app' or 'cli')"
exit 1
;;
esac
TEMPLATE_DIR="$WORKSPACE_ROOT_DIR/resources/linux/debian/$ARTIFACT"
# Add a simple test to make sure we're generating the appropriate repository
# name for the stable channel.
if [ "$RELEASE_CHANNEL" = "stable" ]; then
if [ "$REPO_NAME" != "warpdotdev" ]; then
echo "::error ::Unexpected repo name for $RELEASE_CHANNEL channel: $REPO_NAME (expected \"warpdotdev\")"
exit 1
fi
fi
BUILD_ARCH="${BUILD_ARCH:-$(uname -m)}"
if [ "$BUILD_ARCH" = "aarch64" ]; then
ARCH="arm64"
else
ARCH="amd64"
fi
FULL_PACKAGE_NAME="$PACKAGE_NAME-$ARCH"
PKGDIR="$DIST_DIR/debpkg/$FULL_PACKAGE_NAME"
cleanup() {
# Delete the AppDir that was used as a staging area during the bundling
# process.
if [ -d "$PKGDIR" ]; then
rm -rf "$PKGDIR"
fi
}
# Run cleanup() when the script terminates (whether it succeeded or failed).
trap cleanup EXIT
# Construct a directory that contains all of the output data.
rm -rf "$PKGDIR"
mkdir -p "$PKGDIR"
# Populate the directory with the package contents, in the appropriate
# locations.
OPT_DIR="/opt/warpdotdev/$PACKAGE_NAME"
source "$WORKSPACE_ROOT_DIR/script/linux/bundle_install" "$PKGDIR"
# Move the Debian-specific package metadata into the package directory.
DEBIAN_DIR="$PKGDIR/DEBIAN"
VERSION="$(echo "$GIT_RELEASE_TAG" | sed -E "s/^v//; s/([a-z]+)_/\1./")"
mkdir "$DEBIAN_DIR"
sed \
"s#@@CHANNEL_SUFFIX@@#$CHANNEL_SUFFIX#g; s#@@VERSION@@#$VERSION#g; s#@@ARCH@@#$ARCH#g" \
< "$TEMPLATE_DIR/control.template" \
> "$DEBIAN_DIR/control"
sed \
"s#@@CHANNEL_SUFFIX@@#$CHANNEL_SUFFIX#g; s#@@BINARY_NAME@@#$BINARY_NAME#g; s#@@OPTDIR@@#$OPT_DIR#g; s#@@REPO_NAME@@#$REPO_NAME#g; s#@@CHANNEL@@#$RELEASE_CHANNEL#g; s#@@ARCH@@#$ARCH#g" \
< "$TEMPLATE_DIR/postinst.template" \
> "$DEBIAN_DIR/postinst"
sed \
"s#@@REPO_NAME@@#$REPO_NAME#g; s#@@CHANNEL@@#$RELEASE_CHANNEL#g; s#@@ARCH@@#$ARCH#g" \
< "$WORKSPACE_ROOT_DIR/resources/linux/debian/common/postinst.repo.template" \
>> "$DEBIAN_DIR/postinst"
sed \
"s#@@CHANNEL_SUFFIX@@#$CHANNEL_SUFFIX#g; s#@@OPTDIR@@#$OPT_DIR#g; s#@@REPO_NAME@@#$REPO_NAME#g" \
< "$TEMPLATE_DIR/postrm.template" \
> "$DEBIAN_DIR/postrm"
sed \
"s#@@REPO_NAME@@#$REPO_NAME#g" \
< "$WORKSPACE_ROOT_DIR/resources/linux/debian/common/postrm.repo.template" \
>> "$DEBIAN_DIR/postrm"
# Make the package scripts executable.
chmod 755 \
"$DEBIAN_DIR/postinst" \
"$DEBIAN_DIR/postrm"
# Build the actual package.
cd "$DIST_DIR/debpkg"
fakeroot dpkg-deb -b "$PACKAGE_NAME-$ARCH" "$OUT_DIR"
echo "Successfully built .deb package at $OUT_DIR/${PACKAGE_NAME}_${VERSION}_${ARCH}.deb!"
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
#
# Installs everything built by the bundle script into the given directory.
#
# This is intended to be used when building Linux packages (e.g.: .deb).
#
# Required environment variables:
# - WORKSPACE_ROOT_DIR: The root directory of the Cargo workspace.
# - CARGO_TARGET_OUTPUT_DIR: The cargo target directory containing build output.
# - OPT_DIR: The absolute path to our install directory (under /opt) on the target machine.
# - RELEASE_CHANNEL: The release channel we're bundling (e.g.: "dev").
# - BUNDLE_ID: The app ID for the bundle (e.g.: "dev.warp.WarpDev").
# - EXECUTABLE_PATH: The path to the compiled executable we want to install.
# - BINARY_NAME: The name that the compiled executable should have on the target machine.
# - ARTIFACT: Which artifact to build: app or cli.
set -e
# The target directory should be the first (and only) positional argument.
if [[ $# -gt 1 ]]; then
echo "Expected 1 argument but received $#!"
exit 1
fi
TARGET_DIR="$1"
# Make sure the target directory is empty.
if [[ ! -z "$(ls -A "$TARGET_DIR")" ]]; then
echo "Target directory '$TARGET_DIR' not empty!"
exit 1
fi
# Copy files to the desired output locations within the target dir, stripping
# debugging symbols from the installed binaries.
install -D "$EXECUTABLE_PATH" "${TARGET_DIR}${OPT_DIR}/$BINARY_NAME"
# Only install desktop file and icons if the artifact is "app"
if [[ "$ARTIFACT" == "app" ]]; then
install -Dm644 "$WORKSPACE_ROOT_DIR/app/channels/$RELEASE_CHANNEL/$BUNDLE_ID.desktop" "${TARGET_DIR}/usr/share/applications/$BUNDLE_ID.desktop"
for size in 16x16 32x32 64x64 128x128 256x256 512x512; do
src_path="$WORKSPACE_ROOT_DIR/app/channels/$RELEASE_CHANNEL/icon/no-padding/$size.png"
if [[ -f "$src_path" ]]; then
install -Dm644 "$src_path" "${TARGET_DIR}/usr/share/icons/hicolor/$size/apps/$BUNDLE_ID.png"
fi
done
fi
# Prepare the bundled resources directory.
"$WORKSPACE_ROOT_DIR/script/prepare_bundled_resources" "${TARGET_DIR}/${OPT_DIR}/resources" "$RELEASE_CHANNEL" "$CARGO_PROFILE"
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env bash
#
# Builds a .rpm package as part of the bundling process.
#
# Required environment variables:
# - WORKSPACE_ROOT_DIR: The root directory of the Cargo workspace.
# - DIST_DIR: A temporary directory we can use for staging files as we build the package.
# - OUT_DIR: The directory into which we should place the final package.
# - CARGO_TARGET_OUTPUT_DIR: The cargo target directory containing build output.
# - RELEASE_CHANNEL: The release channel we're bundling (e.g.: "dev").
# - BUNDLE_ID: The app ID for the bundle (e.g.: "dev.warp.WarpDev").
# - EXECUTABLE_PATH: The path to the compiled executable we want to install.
# - BINARY_NAME: The name that the compiled executable should have on the target machine.
# - ARTIFACT: Which artifact to build: app or cli.
set -e
# Extract channel suffix from BINARY_NAME
if [ "$ARTIFACT" = "cli" ]; then
CHANNEL_SUFFIX="${BINARY_NAME#oz}"
else
CHANNEL_SUFFIX="${BINARY_NAME#warp}"
fi
REPO_NAME="warpdotdev$CHANNEL_SUFFIX"
# On Linux, we keep the `-stable` suffix for stable to avoid package conflicts.
# The binary name is still `oz`, and the repo name is still `warpdotdev`.
if [ "$ARTIFACT" = "cli" -a "$RELEASE_CHANNEL" = "stable" ]; then
CHANNEL_SUFFIX="-stable"
fi
ARTIFACT="${ARTIFACT:-app}"
if [ "$ARTIFACT" = "app" ]; then
PACKAGE_NAME="warp-terminal$CHANNEL_SUFFIX"
elif [ "$ARTIFACT" = "cli" ]; then
PACKAGE_NAME="oz$CHANNEL_SUFFIX"
else
echo "::error ::Unknown ARTIFACT: $ARTIFACT (expected 'app' or 'cli')"
exit 1
fi
BUILD_ARCH="${BUILD_ARCH:-$(uname -m)}"
if [ "$BUILD_ARCH" = "aarch64" ]; then
ARCH="aarch64"
else
ARCH="x86_64"
fi
RPMBUILD_DIR="$DIST_DIR/rpmbuild"
FULL_PACKAGE_NAME="$PACKAGE_NAME-$ARCH"
PKGDIR="$DIST_DIR/rpmpkg/$FULL_PACKAGE_NAME"
cleanup() {
# Delete the rpmbuild directory where the build took place.
if [ -d "$RPMBUILD_DIR" ]; then
rm -rf "$RPMBUILD_DIR"
fi
}
# Run cleanup() when the script terminates (whether it succeeded or failed).
trap cleanup EXIT
# Construct a directory that contains the build tree.
rm -rf "$RPMBUILD_DIR"
mkdir -p "$RPMBUILD_DIR"/{SPEC,RPMS}
# Move the RPM-specific package metadata into the package directory.
VERSION="$GIT_RELEASE_TAG"
RELEASE="1"
sed \
"s#@@CHANNEL_SUFFIX@@#$CHANNEL_SUFFIX#g; \
s#@@BINARY_NAME@@#$BINARY_NAME#g; \
s#@@VERSION@@#$VERSION#g; \
s#@@RELEASE@@#$RELEASE#g; \
s#@@ARCH@@#$ARCH#g; \
s#@@WORKSPACEROOT@@#$WORKSPACE_ROOT_DIR#g; \
s#@@BUNDLEID@@#$BUNDLE_ID#g; \
s#@@REPO_NAME@@#$REPO_NAME#g; \
s#@@RELEASE_CHANNEL@@#$RELEASE_CHANNEL#g" \
< "$WORKSPACE_ROOT_DIR/resources/linux/rpm/$ARTIFACT/warp.spec.template" \
> "$RPMBUILD_DIR/SPEC/warp.spec"
# Build the actual package.
fakeroot rpmbuild -v -bb "$RPMBUILD_DIR/SPEC/warp.spec" --target="$ARCH" --define "_topdir $RPMBUILD_DIR"
# Copy the package to the output directory.
RPM_NAME="$PACKAGE_NAME-$VERSION-$RELEASE.$ARCH.rpm"
cp "$RPMBUILD_DIR/RPMS/$ARCH/$RPM_NAME" "$OUT_DIR"
# If we're running on GitHub, sign the package using our signing key that
# should have already been added to the gpg-agent with a preset passphrase.
if [ "${GITHUB_ACTIONS}" == "true" ]; then
# Import our signing key's public key into rpm so the signature can be
# verified.
sudo rpm --import https://releases.warp.dev/linux/keys/warp.asc
# We use batch mode with tty-based pin entry to ensure that the build doesn't
# hang waiting on user input if, for some reason, we failed to preset the
# passphrase for the signing key in the gpg-agent cache.
#
# Additionally, until we know that this works, don't let an error here fail
# the build.
rpmsign \
--verbose \
--addsign --key-id "linux-maintainers@warp.dev" \
--define "_gpg_sign_cmd_extra_args --batch --yes --pinentry-mode loopback" --define "_gpg_digest_algo sha256" \
"$OUT_DIR/$RPM_NAME" \
|| true
fi
echo "Successfully built .rpm package at $OUT_DIR/$RPM_NAME!"
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
#
# Install all dependencies required to build Warp on Linux.
set -e
# Define some control sequences for text formatting.
red="\033[0;31m"
reset="\033[0m"
# Install some development libraries that will be needed in the compilation
# process.
UNAME="$(uname -a)"
if [[ "$(source /etc/os-release; echo $ID $ID_LIKE)" = *"debian"* ]]; then
echo "⬇️ Installing build-time dependencies..."
# Define the packages to install as a bash array so we can include
# comments between lines.
PACKAGES=(
curl
git
# Install various core packages for development work on Linux.
build-essential cmake pkg-config
# Make it so that running `python` runs `python3`.
python-is-python3
# Development headers for various libraries, needed when compiling
# certain Rust crate dependencies.
libssl-dev libfreetype-dev libexpat1-dev libgit2-dev
# libs needed for loading system fonts
libfontconfig1-dev
# Needed in wasm compilation for parsing the version of wasm-bindgen
jq
# Needed for compressing web bundles
brotli
# Needed for voice input
libasound2-dev
)
sudo apt-get install -y "${PACKAGES[@]}"
# Install a modern version of protoc. The apt 'protobuf-compiler' package on
# Ubuntu 20.04 ships protoc 3.6.1, which is too old for proto3 'optional'
# fields (requires protoc >= 3.15).
PROTOC_VERSION="25.1"
case "$(uname -m)" in
x86_64) PROTOC_ZIP="protoc-${PROTOC_VERSION}-linux-x86_64.zip" ;;
aarch64) PROTOC_ZIP="protoc-${PROTOC_VERSION}-linux-aarch_64.zip" ;;
*) echo "Unsupported architecture for protoc: $(uname -m)"; exit 1 ;;
esac
curl -fsSL -o /tmp/protoc.zip \
"https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/${PROTOC_ZIP}"
sudo unzip -o /tmp/protoc.zip -d /usr/local bin/protoc 'include/*'
rm /tmp/protoc.zip
else
echo -e "⚠️ ${red}Unknown Linux distribution; necessary build dependencies may not be installed!${reset}"
fi
# Install Rust.
"$PWD"/script/install_rust
# Install various build-time dependencies through cargo.
"$PWD"/script/install_cargo_build_deps
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -e
# Ensure the ~/.local/bin directory exists so we can download things into it.
LOCAL_BIN="$HOME/.local/bin"
mkdir -p "$LOCAL_BIN"
# A helper function to download an architecture-dependent AppImage and install
# it in ~/.local/bin.
#
# Usage:
# download_appimage $BINARY_NAME $DOWNLOAD_URL_BASE
#
# Args:
# BINARY_NAME: The name of the AppImage-bundled binary we want to
# download, e.g.: "appimagetool".
# DOWNLOAD_URL_BASE: The URL to the directory containing the architecture-
# specific AppImages.
download_appimage() {
BINARY_NAME="$1"
DOWNLOAD_URL_BASE="$2"
APPIMAGE_NAME="$BINARY_NAME-$(uname -m).AppImage"
if [ -x "$(which "$BINARY_NAME")" ]; then
echo "✅ Found $BINARY_NAME on your PATH."
elif [ -x "$(which "$APPIMAGE_NAME")" ]; then
APPIMAGE_PATH="$(which "$APPIMAGE_NAME")"
APPIMAGE_PARENT_DIR="$(dirname "$APPIMAGE_PATH")"
# Create a symlink so we can invoke it like a normal binary.
ln -s "$APPIMAGE_PATH" "$APPIMAGE_PARENT_DIR/$BINARY_NAME"
echo "✅ Found $APPIMAGE_NAME on your PATH; added $BINARY_NAME symlink."
else
echo "⬇️ Downloading $APPIMAGE_NAME..."
APPIMAGE_PATH="$LOCAL_BIN/$APPIMAGE_NAME"
curl -fL "$DOWNLOAD_URL_BASE/$APPIMAGE_NAME" --output "$APPIMAGE_PATH"
chmod +x "$APPIMAGE_PATH"
# Create a symlink so we can invoke it like a normal binary.
ln -s "$APPIMAGE_PATH" "$LOCAL_BIN/$BINARY_NAME"
fi
}
# Install linuxdeploy, a helper for constructing an AppDir (and then invoking
# appimagetool).
download_appimage "linuxdeploy" "https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20240109-1/"
if [ ! -x "$(which linuxdeploy)" ]; then
echo -e "⚠️ ${red}Please make sure that \"$LOCAL_BIN\" is on your PATH, otherwise some scripts may not work.${reset}"
fi
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
#
# Install all dependencies required to build and run Warp on Linux.
set -e
# Define some control sequences for text formatting.
red="\033[0;31m"
reset="\033[0m"
# Install build dependencies.
"$PWD"/script/linux/install_build_deps
# Install additional runtime dependencies.
UNAME="$(uname -a)"
if [[ "$(source /etc/os-release; echo $ID $ID_LIKE)" = *"debian"* ]]; then
echo "⬇️ Installing runtime dependencies..."
# Define the packages to install as a bash array so we can include
# comments between lines.
PACKAGES=(
locales
# Runtime library to get font information.
fontconfig
# Runtime library for deflate compression.
zlib1g
# Runtime libraries for X11.
libx11-6 libxcb1 libxi6 libxcursor1 libxkbcommon-x11-0
# Runtime libraries for Wayland.
libwayland-client0 libwayland-egl1
# Open-source Vulkan drivers from the mesa project.
mesa-vulkan-drivers
# Runtime libraries for EGL.
libegl1
# Ensuring at least one cursor library for WSL.
yaru-theme-icon
)
sudo apt-get install -y "${PACKAGES[@]}"
else
echo -e "⚠️ ${red}Unknown Linux distribution; necessary runtime dependencies may not be installed!${reset}"
fi
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
#
# Install all dependencies required to build, run, and test Warp on Linux.
set -e
# Define some control sequences for text formatting.
red="\033[0;31m"
reset="\033[0m"
# Install runtime dependencies.
"$PWD"/script/linux/install_runtime_deps
# Install additional testing dependencies.
UNAME="$(uname -a)"
if [[ "$(source /etc/os-release; echo $ID $ID_LIKE)" = *"debian"* ]]; then
echo "⬇️ Installing test dependencies..."
# Define the packages to install as a bash array so we can include
# comments between lines.
PACKAGES=(
# Install the zsh and fish shells.
zsh fish
# We run vim in some integration tests to test the altscreen.
vim
)
sudo apt-get install -y "${PACKAGES[@]}"
# If gcloud is not already installed, install it so that we can run SSH integration tests.
if [[ ! -x "$(command -v gcloud)" ]]; then
echo "⬇️ Installing the gcloud CLI..."
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list
curl -f https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update -y
sudo apt-get install google-cloud-cli -y
fi
else
echo -e "⚠️ ${red}Unknown Linux distribution; necessary test dependencies may not be installed!${reset}"
fi
# Install various testing dependencies through cargo.
"$PWD"/script/install_cargo_test_deps
+79
View File
@@ -0,0 +1,79 @@
#!/bin/bash
#
# linuxdeploy input plugin for restructuring the AppDir to match Warp's
# standard Linux install layout.
#
# By default, linuxdeploy places the executable at usr/bin/ inside the AppDir.
# This plugin moves it to opt/warpdotdev/<package>/ (matching deb/rpm/arch
# package layout), creates a symlink from usr/bin/ to the new location, and
# copies bundled resources alongside the binary.
#
# This means that extracting an AppImage produces the same filesystem layout
# as installing a .deb or .rpm package.
#
# Required environment variables:
# WARP_BINARY_NAME: Name of the binary (e.g. "warp-dev").
# WARP_PACKAGE_NAME: Package directory name (e.g. "warp-terminal-dev").
# WARP_BUNDLED_RESOURCES_DIR: Path to the staged resources directory to copy.
set -e
while [[ "$#" -gt 0 ]]; do
case "$1" in
--plugin-api-version)
echo "0"
exit 0
;;
--appdir)
APPDIR="$2"
shift 2
;;
*)
shift
;;
esac
done
if [ -z "$APPDIR" ]; then
echo "ERROR: --appdir is required" >&2
exit 1
fi
for var in WARP_BINARY_NAME WARP_PACKAGE_NAME WARP_BUNDLED_RESOURCES_DIR; do
if [ -z "${!var}" ]; then
echo "ERROR: $var environment variable is not set" >&2
exit 1
fi
done
if [ ! -d "$WARP_BUNDLED_RESOURCES_DIR" ]; then
echo "ERROR: Bundled resources directory does not exist: $WARP_BUNDLED_RESOURCES_DIR" >&2
exit 1
fi
SRC_BIN="$APPDIR/usr/bin/$WARP_BINARY_NAME"
if [ ! -f "$SRC_BIN" ]; then
echo "ERROR: Expected binary not found at $SRC_BIN" >&2
exit 1
fi
# Create the /opt install directory inside the AppDir.
OPT_DIR="$APPDIR/opt/warpdotdev/$WARP_PACKAGE_NAME"
mkdir -p "$OPT_DIR"
# Move the binary from usr/bin/ to opt/warpdotdev/<package>/.
echo "Relocating binary to $OPT_DIR/$WARP_BINARY_NAME"
mv "$SRC_BIN" "$OPT_DIR/$WARP_BINARY_NAME"
# Create a relative symlink so usr/bin/<name> still resolves to the binary.
# From usr/bin/ to opt/warpdotdev/<package>/ is ../../opt/warpdotdev/<package>/.
echo "Creating symlink at usr/bin/$WARP_BINARY_NAME"
ln -s "../../opt/warpdotdev/$WARP_PACKAGE_NAME/$WARP_BINARY_NAME" "$SRC_BIN"
# Copy bundled resources alongside the binary.
DEST_RESOURCES="$OPT_DIR/resources"
echo "Copying bundled resources to $DEST_RESOURCES"
mkdir -p "$DEST_RESOURCES"
cp -R "$WARP_BUNDLED_RESOURCES_DIR/." "$DEST_RESOURCES/"
echo "Successfully restructured AppDir for Warp"
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#
# Signs the Arch Linux packages in a given directory.
PKGDIR="$1"
for package in $PKGDIR/*.pkg.tar.zst; do
gpg --no-tty --pinentry-mode loopback --detach-sign --no-armor --batch --yes --output $package.sig $package
done