From df6c389e941ae9fb3c6b48caf77599be8939de4c Mon Sep 17 00:00:00 2001 From: VitalyR Date: Thu, 28 May 2026 15:28:21 +0800 Subject: [PATCH] Centralize bundle feature policy in Cargo metadata Package scripts and Nix were drifting from app/Cargo.toml feature policy, so the build matrix now resolves named metadata profiles from the manifest. The profiles use composable cross-cutting feature groups instead of platform/artifact base groups, Nix selects its own profile path, and flake evaluation only resolves that selected profile. Constraint: Upstream master now applies NLD v3 to local/dev app bundles, NLD v2 to preview app bundles, adds Linux/macOS warpctrl artifacts, and keeps macOS preview bundles on heap diagnostics. Rejected: Keeping local/dev app profiles on NLD v2 | would regress the rebased upstream matrix. Rejected: Keeping preview app profiles on NLD v1 | would regress the rebased upstream matrix. Rejected: Dropping macOS preview heap diagnostics | would change current script/macos/bundle preview app, CLI, and warpctrl behavior. Rejected: Omitting Linux/macOS warpctrl profiles | would make the metadata resolver drop an upstream artifact path's warp_control_cli feature. Rejected: Adding agent_debug to windows.local.app | current upstream Windows local builds do not add it, and the human review requested omitting unnecessary local debug features. Rejected: Leaving feature arrays duplicated in platform scripts | would keep the stale flag failure mode from issue #10979. Rejected: Keeping Nix's build profile in Cargo metadata | platform scripts construct their profile paths locally, and the review requested the same convention for Nix. Rejected: Supporting base build-profile groups in resolvers | the review asked to get rid of base groups, so stale base entries now fail validation. Rejected: Validating every Cargo build profile during flake evaluation | full-matrix validation belongs in script/check_cargo_build_profiles, while flake evaluation should only resolve the Nix-selected profile. Confidence: high Scope-risk: moderate Directive: When adding packaging features, add reusable package.metadata.warp.build_feature_groups and compose leaf package.metadata.warp.build_profiles from groups/features only. Tested: script/check_cargo_build_profiles --all; cargo metadata accepted 44 resolved profiles; targeted profile checks for Linux/macOS/Windows NLD v3 local/dev, NLD v2 preview, NLD v1 stable/OSS, macOS preview heap diagnostics, Windows local without agent_debug, and Linux/macOS warpctrl with warp_control_cli; non-leaf and missing profile negative checks for script/check_cargo_build_profiles; nix eval .#warp-terminal-experimental.buildFeatures --json; nix eval .#warp-terminal-experimental.meta.mainProgram --raw; rg found no nld_improvements in flake.nix, app/Cargo.toml, or script; bash -n modified shell scripts; git diff --check origin/master HEAD; git diff --check; git merge-tree --write-tree origin/master HEAD; nix build .#warp-terminal-experimental --no-link --print-out-paths --option download-attempts 8 --option max-jobs 1; independent gpt-5.5 xhigh pre-push review. Not-tested: PowerShell parse on Windows because pwsh is unavailable locally. --- app/Cargo.toml | 213 +++++++++++++++++++++++++ flake.nix | 43 ++++- script/cargo_build_profiles.jq | 57 +++++++ script/cargo_bundle_features.sh | 16 ++ script/check_cargo_build_profiles | 108 +++++++++++++ script/deploy_remote_server | 3 +- script/deploy_remote_server_to_test_vm | 3 +- script/linux/bundle | 33 +--- script/macos/bundle | 38 ++--- script/run | 16 +- script/wasm/bundle | 7 +- script/windows/bundle.ps1 | 41 +++-- 12 files changed, 506 insertions(+), 72 deletions(-) create mode 100644 script/cargo_build_profiles.jq create mode 100755 script/cargo_bundle_features.sh create mode 100755 script/check_cargo_build_profiles diff --git a/app/Cargo.toml b/app/Cargo.toml index c0d01239e9..2d821a39ec 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -996,6 +996,219 @@ cloud_mode_input_v2 = ["cloud_mode"] handoff_cloud_cloud = ["cloud_mode_setup_v2"] git_credential_refresh = [] +# Declarative packaging build profiles consumed by `flake.nix` and the bundle +# scripts. Feature atoms stay in `build_feature_groups`; profiles combine +# composable cross-cutting groups plus optional direct `features`. +[package.metadata.warp.build_feature_groups] +# Artifact shape. +app = [ + "release_bundle", + "gui", +] +cli = [ + "release_bundle", + "standalone", +] +gui_entrypoint = [ + "gui", +] +release_artifact = [ + "release_bundle", +] + +# Platform/official-distribution features. +linux_official = [ + "crash_reporting", +] +windows_official = [ + "crash_reporting", +] +macos_official = [ + "cocoa_sentry", +] +macos_common = [ + "extern_plist", +] + +# Additional build behavior. +agent_debug = [ + "agent_mode_debug", +] +linux_dev_diagnostics = [ + "agent_mode_debug", + "jemalloc_pprof", +] +macos_dev_diagnostics = [ + "agent_mode_debug", + "jemalloc_pprof", + "heap_usage_tracking", +] +macos_heap_diagnostics = [ + "jemalloc_pprof", + "heap_usage_tracking", +] +preview_channel = [ + "preview_channel", +] +remote_tty = [ + "remote_tty", +] +remote_server = [ + "crash_reporting", + "standalone", + "agent_mode_debug", + "remote_codebase_indexing", +] +warp_control = [ + "warp_control_cli", +] +nld_v1 = [ + "nld_classifier_v1", + "nld_heuristic_v1", +] +nld_v2 = [ + "nld_classifier_v2", + "nld_heuristic_v2", +] +nld_v3 = [ + "nld_classifier_v3", + "nld_heuristic_v2", +] + +[package.metadata.warp.build_profiles.linux.local.app] +groups = ["app", "linux_official", "agent_debug", "nld_v3"] + +[package.metadata.warp.build_profiles.linux.dev.app] +groups = ["app", "linux_official", "linux_dev_diagnostics", "nld_v3"] + +[package.metadata.warp.build_profiles.linux.preview.app] +groups = ["app", "linux_official", "preview_channel", "nld_v2"] + +[package.metadata.warp.build_profiles.linux.stable.app] +groups = ["app", "linux_official", "nld_v1"] + +[package.metadata.warp.build_profiles.linux.oss.app] +groups = ["app", "nld_v1"] + +[package.metadata.warp.build_profiles.linux.local.cli] +groups = ["cli", "linux_official", "agent_debug"] + +[package.metadata.warp.build_profiles.linux.dev.cli] +groups = ["cli", "linux_official", "linux_dev_diagnostics"] + +[package.metadata.warp.build_profiles.linux.preview.cli] +groups = ["cli", "linux_official", "preview_channel"] + +[package.metadata.warp.build_profiles.linux.stable.cli] +groups = ["cli", "linux_official"] + +[package.metadata.warp.build_profiles.linux.oss.cli] +groups = ["cli"] + +[package.metadata.warp.build_profiles.linux.local.warpctrl] +groups = ["cli", "linux_official", "agent_debug", "warp_control"] + +[package.metadata.warp.build_profiles.linux.dev.warpctrl] +groups = ["cli", "linux_official", "linux_dev_diagnostics", "warp_control"] + +[package.metadata.warp.build_profiles.linux.preview.warpctrl] +groups = ["cli", "linux_official", "preview_channel", "warp_control"] + +[package.metadata.warp.build_profiles.linux.stable.warpctrl] +groups = ["cli", "linux_official", "warp_control"] + +[package.metadata.warp.build_profiles.linux.oss.warpctrl] +groups = ["cli", "warp_control"] + +[package.metadata.warp.build_profiles.macos.local.app] +groups = ["app", "macos_common", "macos_official", "agent_debug", "nld_v3"] + +[package.metadata.warp.build_profiles.macos.dev.app] +groups = ["app", "macos_common", "macos_official", "macos_dev_diagnostics", "nld_v3"] + +[package.metadata.warp.build_profiles.macos.preview.app] +groups = ["app", "macos_common", "macos_official", "preview_channel", "macos_heap_diagnostics", "nld_v2"] + +[package.metadata.warp.build_profiles.macos.stable.app] +groups = ["app", "macos_common", "macos_official", "macos_heap_diagnostics", "nld_v1"] + +[package.metadata.warp.build_profiles.macos.oss.app] +groups = ["app", "macos_common", "nld_v1"] + +[package.metadata.warp.build_profiles.macos.local.cli] +groups = ["cli", "macos_common", "macos_official", "agent_debug"] + +[package.metadata.warp.build_profiles.macos.dev.cli] +groups = ["cli", "macos_common", "macos_official", "macos_dev_diagnostics"] + +[package.metadata.warp.build_profiles.macos.preview.cli] +groups = ["cli", "macos_common", "macos_official", "preview_channel", "macos_heap_diagnostics"] + +[package.metadata.warp.build_profiles.macos.stable.cli] +groups = ["cli", "macos_common", "macos_official", "macos_heap_diagnostics"] + +[package.metadata.warp.build_profiles.macos.oss.cli] +groups = ["cli", "macos_common"] + +[package.metadata.warp.build_profiles.macos.local.warpctrl] +groups = ["cli", "macos_common", "macos_official", "agent_debug", "warp_control"] + +[package.metadata.warp.build_profiles.macos.dev.warpctrl] +groups = ["cli", "macos_common", "macos_official", "macos_dev_diagnostics", "warp_control"] + +[package.metadata.warp.build_profiles.macos.preview.warpctrl] +groups = ["cli", "macos_common", "macos_official", "preview_channel", "macos_heap_diagnostics", "warp_control"] + +[package.metadata.warp.build_profiles.macos.stable.warpctrl] +groups = ["cli", "macos_common", "macos_official", "macos_heap_diagnostics", "warp_control"] + +[package.metadata.warp.build_profiles.macos.oss.warpctrl] +groups = ["cli", "macos_common", "warp_control"] + +[package.metadata.warp.build_profiles.windows.local.app] +groups = ["app", "windows_official", "nld_v3"] + +[package.metadata.warp.build_profiles.windows.dev.app] +groups = ["app", "windows_official", "agent_debug", "nld_v3"] + +[package.metadata.warp.build_profiles.windows.preview.app] +groups = ["app", "windows_official", "preview_channel", "nld_v2"] + +[package.metadata.warp.build_profiles.windows.stable.app] +groups = ["app", "windows_official", "nld_v1"] + +[package.metadata.warp.build_profiles.windows.oss.app] +groups = ["app", "nld_v1"] + +# Run-entrypoint feature profiles used by `script/run`. +[package.metadata.warp.build_profiles.run.local] +groups = ["gui_entrypoint"] + +[package.metadata.warp.build_profiles.run.oss] +groups = ["gui_entrypoint"] + +# Additional build profiles used by web/remote-server packaging paths. +[package.metadata.warp.build_profiles.wasm.local] +groups = ["app", "remote_tty"] + +[package.metadata.warp.build_profiles.wasm.dev] +groups = ["app"] + +[package.metadata.warp.build_profiles.wasm.preview] +groups = ["app", "preview_channel"] + +[package.metadata.warp.build_profiles.wasm.stable] +groups = ["app"] + +[package.metadata.warp.build_profiles.wasm.oss] +groups = ["app"] + +[package.metadata.warp.build_profiles.remote_server.deploy] +groups = ["release_artifact", "remote_server"] + +[package.metadata.warp.build_profiles.remote_server.integration] +groups = ["remote_server"] + [package.metadata.bundle.bin.warp-oss] category = "public.app-category.developer-tools" copyright = "© 2025, Denver Technologies, Inc" diff --git a/flake.nix b/flake.nix index 2dc81648b5..a069e3a159 100644 --- a/flake.nix +++ b/flake.nix @@ -123,10 +123,45 @@ zlib ]; - buildFeatures = [ - "release_bundle" - "gui" - ]; + warpMetadata = appCargoToml.package.metadata.warp; + buildFeatureGroups = warpMetadata.build_feature_groups; + buildProfiles = warpMetadata.build_profiles; + nixBuildProfile = "linux.oss.app"; + profileGroupNames = profile: profile.groups or [ ]; + hasProfileFeatures = + profile: builtins.isAttrs profile && (profile ? groups || profile ? features); + hasUnsupportedBaseGroup = + profile: builtins.isAttrs profile && profile ? base; + resolveBuildProfileFeatures = + profilePath: + let + profilePathSegments = lib.splitString "." profilePath; + profileExists = lib.attrsets.hasAttrByPath profilePathSegments buildProfiles; + profile = lib.attrsets.getAttrFromPath profilePathSegments buildProfiles; + groupNames = profileGroupNames profile; + missingGroups = builtins.filter (group: !(builtins.hasAttr group buildFeatureGroups)) groupNames; + groupFeatures = lib.concatMap (group: buildFeatureGroups.${group}) ( + builtins.filter (group: builtins.hasAttr group buildFeatureGroups) groupNames + ); + directFeatures = profile.features or [ ]; + features = lib.lists.uniqueStrings (groupFeatures ++ directFeatures); + missingFeatures = builtins.filter ( + feature: !(builtins.hasAttr feature appCargoToml.features) + ) features; + in + if !profileExists then + throw "app/Cargo.toml package.metadata.warp.build_profiles.${profilePath} is missing" + else if hasUnsupportedBaseGroup profile then + throw "app/Cargo.toml package.metadata.warp.build_profiles.${profilePath} uses unsupported base build group; use groups instead" + else if !(hasProfileFeatures profile) then + throw "app/Cargo.toml package.metadata.warp.build_profiles.${profilePath} is not a leaf build profile" + else if missingGroups != [ ] then + throw "app/Cargo.toml package.metadata.warp.build_profiles.${profilePath} references undefined build feature groups: ${lib.concatStringsSep ", " missingGroups}" + else if missingFeatures != [ ] then + throw "app/Cargo.toml package.metadata.warp.build_profiles.${profilePath} references undefined Cargo features: ${lib.concatStringsSep ", " missingFeatures}" + else + features; + buildFeatures = resolveBuildProfileFeatures nixBuildProfile; warp-terminal-experimental = rustPlatform.buildRustPackage { pname = "warp-terminal-experimental"; diff --git a/script/cargo_build_profiles.jq b/script/cargo_build_profiles.jq new file mode 100644 index 0000000000..a8751ec4f0 --- /dev/null +++ b/script/cargo_build_profiles.jq @@ -0,0 +1,57 @@ +def descend($segments): + reduce $segments[] as $segment ( + .; + if type == "object" and has($segment) then .[$segment] else null end + ); + +def unique_preserve_order: + reduce .[] as $item ([]; if index($item) == null then . + [$item] else . end); + +def profile_group_names: + .groups // []; + +def has_profile_features: + type == "object" and (has("groups") or has("features")); + +def has_unsupported_base_group: + type == "object" and has("base"); + +def resolve_profile($package; $profile_path): + ($package.metadata.warp.build_profiles | descend($profile_path | split("."))) as $profile + | if $profile == null then + error("Missing Cargo build profile: \($profile_path)") + elif ($profile | has_unsupported_base_group) then + error("Cargo build profile uses unsupported base build group; use groups instead: \($profile_path)") + elif ($profile | has_profile_features | not) then + error("Cargo build profile path is not a leaf build profile: \($profile_path)") + else + ($package.metadata.warp.build_feature_groups // {}) as $feature_groups + | ($profile | profile_group_names) as $group_names + | reduce $group_names[] as $group_name ( + { features: [], missing_groups: [] }; + if ($feature_groups | has($group_name)) then + .features += ($feature_groups[$group_name] // []) + else + .missing_groups += [$group_name] + end + ) as $group_result + | if ($group_result.missing_groups | length) > 0 then + error("Cargo build profile \($profile_path) references undefined build feature groups: \($group_result.missing_groups | join(", "))") + else + (($group_result.features + ($profile.features // [])) | unique_preserve_order) as $features + | ($package.features | keys) as $available_features + | [ + $features[] + | select((. as $feature | $available_features | index($feature)) | not) + ] as $missing_features + | if ($missing_features | length) > 0 then + error("Cargo build profile \($profile_path) references undefined Cargo features: \($missing_features | join(", "))") + else + $features | join(",") + end + end + end; + +.packages[] +| select(.name == "warp") +| resolve_profile(.; $profile_path) diff --git a/script/cargo_bundle_features.sh b/script/cargo_bundle_features.sh new file mode 100755 index 0000000000..4bf1f76f8b --- /dev/null +++ b/script/cargo_bundle_features.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# +# Resolve declarative Cargo build profiles from app/Cargo.toml. +# +# The profile path is a dot-separated path under +# `package.metadata.warp.build_profiles`, for example: +# linux.oss.app +# macos.dev.cli +# windows.preview.app + +resolve_cargo_bundle_features() { + local workspace_root_dir="$1" + local profile_path="$2" + + "$workspace_root_dir/script/check_cargo_build_profiles" --profile "$profile_path" +} diff --git a/script/check_cargo_build_profiles b/script/check_cargo_build_profiles new file mode 100755 index 0000000000..ed996f04e3 --- /dev/null +++ b/script/check_cargo_build_profiles @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat <<'USAGE' +Usage: script/check_cargo_build_profiles [--all] [--profile PROFILE] + +Validate Cargo build profiles declared in app/Cargo.toml. + +Options: + --all Validate every package.metadata.warp.build_profiles entry. + --profile PROFILE Resolve one dot-path profile, e.g. linux.oss.app. + -h, --help Show this help. + +When --profile is used, the resolved comma-separated feature list is printed. +USAGE +} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORKSPACE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +MANIFEST_PATH="$WORKSPACE_ROOT_DIR/app/Cargo.toml" +JQ_FILTER="$SCRIPT_DIR/cargo_build_profiles.jq" +VALIDATE_ALL=0 +PROFILE_PATH="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --all) + VALIDATE_ALL=1 + shift + ;; + --profile) + if [[ $# -lt 2 ]]; then + echo "Error: --profile requires a value" >&2 + exit 1 + fi + PROFILE_PATH="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Error: unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ $VALIDATE_ALL -eq 1 && -n "$PROFILE_PATH" ]]; then + echo "Error: use either --all or --profile, not both" >&2 + exit 1 +fi + +if [[ $VALIDATE_ALL -eq 0 && -z "$PROFILE_PATH" ]]; then + usage >&2 + exit 1 +fi + +if ! command -v jq >/dev/null 2>&1; then + echo "Error: jq is required to validate Cargo build profiles." >&2 + exit 1 +fi + +METADATA_JSON="$(cargo metadata --format-version 1 --no-deps --locked --manifest-path "$MANIFEST_PATH")" + +resolve_profile() { + local profile_path="$1" + printf '%s' "$METADATA_JSON" | jq -er --arg profile_path "$profile_path" -f "$JQ_FILTER" +} + +list_profile_paths() { + printf '%s' "$METADATA_JSON" | jq -r ' + .packages[] + | select(.name == "warp") + | .metadata.warp.build_profiles + | paths(objects) as $path + | getpath($path) as $value + | select( + ($value | type) == "object" + and (($value | has("base")) or ($value | has("groups")) or ($value | has("features"))) + ) + | $path + | map(tostring) + | join(".") + ' +} + +if [[ -n "$PROFILE_PATH" ]]; then + resolve_profile "$PROFILE_PATH" + exit 0 +fi + +PROFILE_COUNT=0 +while IFS= read -r profile_path; do + [[ -z "$profile_path" ]] && continue + resolve_profile "$profile_path" >/dev/null + PROFILE_COUNT=$((PROFILE_COUNT + 1)) +done < <(list_profile_paths) + +if [[ $PROFILE_COUNT -eq 0 ]]; then + echo "Error: no Cargo build profiles found in app/Cargo.toml" >&2 + exit 1 +fi + +echo "Validated $PROFILE_COUNT Cargo build profiles." diff --git a/script/deploy_remote_server b/script/deploy_remote_server index 3d4e810983..67b7e8299d 100755 --- a/script/deploy_remote_server +++ b/script/deploy_remote_server @@ -17,6 +17,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +source "$WORKSPACE_ROOT/script/cargo_bundle_features.sh" # Defaults PROFILE_MODE="dev-remote" @@ -109,7 +110,7 @@ case "$PROFILE_MODE" in ;; esac -FEATURES="release_bundle,crash_reporting,standalone,agent_mode_debug,remote_codebase_indexing" +FEATURES="$(resolve_cargo_bundle_features "$WORKSPACE_ROOT" "remote_server.deploy")" WARP_BIN="warp" BINARY_NAME="oz-local" REMOTE_DIR=".warp-local/remote-server" diff --git a/script/deploy_remote_server_to_test_vm b/script/deploy_remote_server_to_test_vm index 9c5c9b9cd1..f598a234eb 100755 --- a/script/deploy_remote_server_to_test_vm +++ b/script/deploy_remote_server_to_test_vm @@ -22,10 +22,11 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +source "$WORKSPACE_ROOT/script/cargo_bundle_features.sh" TARGET="x86_64-unknown-linux-musl" CARGO_PROFILE="dev-remote" -FEATURES="crash_reporting,standalone,agent_mode_debug,remote_codebase_indexing" +FEATURES="$(resolve_cargo_bundle_features "$WORKSPACE_ROOT" "remote_server.integration")" WARP_BIN="integration" # The integration test runner uses Channel::Integration, which maps to # cli_command_name() = "oz-integration", remote_server_dir() = "~/.warp-dev/remote-server", diff --git a/script/linux/bundle b/script/linux/bundle index 0caeed04e0..9a8035d639 100755 --- a/script/linux/bundle +++ b/script/linux/bundle @@ -5,6 +5,7 @@ set -e WORKSPACE_ROOT_DIR="$(pwd)" +source "$WORKSPACE_ROOT_DIR/script/cargo_bundle_features.sh" CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORKSPACE_ROOT_DIR/target}" DIST_DIR="$CARGO_TARGET_DIR/dist" @@ -21,7 +22,6 @@ trap cleanup EXIT # By default we build dev bundles. RELEASE_CHANNEL="dev" -FEATURES="release_bundle,crash_reporting" EXTRA_FEATURES="" PACKAGES=( appimage ) BUILD="true" @@ -163,21 +163,16 @@ 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" @@ -186,9 +181,8 @@ elif [[ $RELEASE_CHANNEL = "oss" ]]; then WARP_BIN="warp-oss" BINARY_NAME="warp-oss" APP_NAME="WarpOss" - # The OSS channel does not ship Sentry, so drop the crash_reporting feature - # (which would otherwise pull in the Sentry SDK as a dependency). - FEATURES="release_bundle" + # The OSS channel's Cargo build profile does not ship Sentry, so it omits the + # crash_reporting feature that would otherwise pull in the Sentry SDK. fi # Artifact-specific binary naming @@ -204,25 +198,14 @@ elif [[ "$ARTIFACT" == "warpctrl" ]]; then PACKAGES=() fi -# Artifact-specific configuration -if [[ "$ARTIFACT" == "cli" || "$ARTIFACT" == "warpctrl" ]]; then - FEATURES="$FEATURES,standalone" - if [[ "$ARTIFACT" == "warpctrl" ]]; then - FEATURES="$FEATURES,warp_control_cli" - fi -elif [[ "$ARTIFACT" == "app" ]]; then - FEATURES="$FEATURES,gui" - if [[ "$RELEASE_CHANNEL" == "local" || "$RELEASE_CHANNEL" == "dev" ]]; then - FEATURES="$FEATURES,nld_classifier_v3,nld_heuristic_v2" - elif [[ "$RELEASE_CHANNEL" == "preview" ]]; then - FEATURES="$FEATURES,nld_classifier_v2,nld_heuristic_v2" - else - FEATURES="$FEATURES,nld_classifier_v1,nld_heuristic_v1" - fi -fi +# Artifact-specific Cargo features are captured by the metadata profile below. + +CARGO_FEATURE_PROFILE="linux.${RELEASE_CHANNEL}.${ARTIFACT}" +FEATURES="$(resolve_cargo_bundle_features "$WORKSPACE_ROOT_DIR" "$CARGO_FEATURE_PROFILE")" if [[ -n "$EXTRA_FEATURES" ]]; then FEATURES="$FEATURES,$EXTRA_FEATURES" fi +echo "Using Cargo build profile $CARGO_FEATURE_PROFILE with features: $FEATURES" BUNDLE_ID="dev.warp.$APP_NAME" EXECUTABLE_PATH="$CARGO_TARGET_OUTPUT_DIR/$WARP_BIN" diff --git a/script/macos/bundle b/script/macos/bundle index f1ee751965..6036433ef7 100755 --- a/script/macos/bundle +++ b/script/macos/bundle @@ -44,6 +44,7 @@ set -e # Determine the repository root directory WORKSPACE_ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$WORKSPACE_ROOT_DIR/script/cargo_bundle_features.sh" # This is used to set the minimum deployment target for mac # https://cmake.org/cmake/help/latest/envvar/MACOSX_DEPLOYMENT_TARGET.html @@ -99,7 +100,7 @@ TARGET_ARCH="" DMG_NAME_SUFFIX="" # By default we build dev bundles. RELEASE_CHANNEL="dev" -FEATURES="release_bundle,cocoa_sentry,extern_plist" +EXTRA_FEATURES="" REGISTER_SERVICES=true DEBUG=false ARTIFACT="app" @@ -214,7 +215,11 @@ while (( "$#" )); do --features) if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then echo "Adding Cargo features: $2" - FEATURES="$FEATURES,$2" + if [[ -z "$EXTRA_FEATURES" ]]; then + EXTRA_FEATURES="$2" + else + EXTRA_FEATURES="$EXTRA_FEATURES,$2" + fi shift 2 else echo "Error: Argument for $1 is missing" >&2 @@ -273,7 +278,6 @@ if [[ $RELEASE_CHANNEL = "local" ]]; then 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`. @@ -283,9 +287,6 @@ elif [[ $RELEASE_CHANNEL = "dev" ]]; then 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`. @@ -296,24 +297,16 @@ elif [[ $RELEASE_CHANNEL = "preview" ]]; then 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" @@ -350,18 +343,15 @@ fi if [[ "$ARTIFACT" == cli || "$ARTIFACT" == warpctrl ]]; 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_v3,nld_heuristic_v2" - elif [[ "$RELEASE_CHANNEL" == "preview" ]]; then - FEATURES="$FEATURES,nld_classifier_v2,nld_heuristic_v2" - else - FEATURES="$FEATURES,nld_classifier_v1,nld_heuristic_v1" - fi fi +CARGO_FEATURE_PROFILE="macos.${RELEASE_CHANNEL}.${ARTIFACT}" +FEATURES="$(resolve_cargo_bundle_features "$WORKSPACE_ROOT_DIR" "$CARGO_FEATURE_PROFILE")" +if [[ -n "$EXTRA_FEATURES" ]]; then + FEATURES="$FEATURES,$EXTRA_FEATURES" +fi +echo "Using Cargo build profile $CARGO_FEATURE_PROFILE with features: $FEATURES" + # 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" diff --git a/script/run b/script/run index 059af5f563..bd5c141ce7 100755 --- a/script/run +++ b/script/run @@ -15,10 +15,11 @@ set -e REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)" cd "${REPO_ROOT}" +source "$REPO_ROOT/script/cargo_bundle_features.sh" OS_TYPE="$(uname -s)" -FEATURES="gui" +EXTRA_FEATURES="" INSTALL_COMMON_SKILLS=1 FORCE_COMMON_SKILLS=0 COMMON_SKILLS_TARGET="${WARP_COMMON_SKILLS_INSTALL_TARGET:-}" @@ -51,7 +52,11 @@ while (( "$#" )); do ;; --features) if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then - FEATURES="$FEATURES,$2" + if [[ -z "$EXTRA_FEATURES" ]]; then + EXTRA_FEATURES="$2" + else + EXTRA_FEATURES="$EXTRA_FEATURES,$2" + fi shift 2 else echo "Error: Argument for $1 is missing" >&2 @@ -122,6 +127,13 @@ if [[ "$INSTALL_COMMON_SKILLS" -eq 1 ]]; then fi fi +CARGO_FEATURE_PROFILE="run.${WARP_CHANNEL}" +FEATURES="$(resolve_cargo_bundle_features "$REPO_ROOT" "$CARGO_FEATURE_PROFILE")" +if [[ -n "$EXTRA_FEATURES" ]]; then + FEATURES="$FEATURES,$EXTRA_FEATURES" +fi +echo "Using Cargo build profile $CARGO_FEATURE_PROFILE with features: $FEATURES" + # These cargo features were removed and replaced by environment variables read # by warp-channel-config. Intercept them here so that existing --features # invocations keep working. diff --git a/script/wasm/bundle b/script/wasm/bundle index 73b231937f..c71620cded 100755 --- a/script/wasm/bundle +++ b/script/wasm/bundle @@ -16,13 +16,13 @@ if [[ "$OSTYPE" == "darwin"* ]]; then fi WORKSPACE_ROOT_DIR="$(pwd)" +source "$WORKSPACE_ROOT_DIR/script/cargo_bundle_features.sh" CARGO_TARGET_DIR="$WORKSPACE_ROOT_DIR/target/wasm32-unknown-unknown" # By default we build dev bundles. RELEASE_CHANNEL="dev" # TODO: We should enable crash_reporting and before enabling for trusted testers. # https://linear.app/warpdotdev/issue/PLAT-428/crash-reporting-on-web -FEATURES="release_bundle,gui" DEBUG=false PARAMS="" @@ -118,21 +118,22 @@ mkdir -p "$EXTRAS_DIR" # N.B. The bundled outputs will always be warp.js and warp_bg.wasm. if [[ $RELEASE_CHANNEL = "local" ]]; then WARP_BIN="warp" - FEATURES="$FEATURES,remote_tty" elif [[ $RELEASE_CHANNEL = "dev" ]]; then WARP_BIN="dev" elif [[ $RELEASE_CHANNEL = "preview" ]]; then WARP_BIN="preview" - FEATURES="$FEATURES,preview_channel" elif [[ $RELEASE_CHANNEL = "stable" ]]; then WARP_BIN="stable" elif [[ $RELEASE_CHANNEL = "oss" ]]; then WARP_BIN="warp-oss" fi +CARGO_FEATURE_PROFILE="wasm.${RELEASE_CHANNEL}" +FEATURES="$(resolve_cargo_bundle_features "$WORKSPACE_ROOT_DIR" "$CARGO_FEATURE_PROFILE")" if [ -n "${FEATURES_OVERRIDE+x}" ]; then FEATURES="$FEATURES_OVERRIDE" fi +echo "Using Cargo build profile $CARGO_FEATURE_PROFILE with features: $FEATURES" # 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 diff --git a/script/windows/bundle.ps1 b/script/windows/bundle.ps1 index 616f8edada..f039cb9eab 100644 --- a/script/windows/bundle.ps1 +++ b/script/windows/bundle.ps1 @@ -14,7 +14,8 @@ Param ( [Alias('release-tag')] [String]$RELEASE_TAG = '', - [String]$FEATURES = 'release_bundle,crash_reporting,gui', + # Additional Cargo features to append to the Cargo.toml profile. + [String]$FEATURES = '', # Builds only the Warp binary, skips the installer. [Switch]$SKIP_BUILD_INSTALLER = $False, @@ -62,6 +63,29 @@ $ErrorActionPreference = 'Stop' $WORKSPACE_ROOT_DIR = $(Get-Location).Path $CARGO_TARGET_DIR = $WORKSPACE_ROOT_DIR + '\target' $WINDOWS_INSTALLER_DIR = $WORKSPACE_ROOT_DIR + '\script\windows' +$EXTRA_FEATURES = $FEATURES + +function Resolve-CargoBundleFeatures { + param( + [Parameter(Mandatory = $true)] + [String]$WorkspaceRootDir, + [Parameter(Mandatory = $true)] + [String]$ProfilePath + ) + + if (-Not (Get-Command -Name jq -Type Application -ErrorAction SilentlyContinue)) { + throw 'jq is required to resolve Cargo build profiles. Run script\windows\bootstrap.ps1 to install build dependencies.' + } + + $jqFilter = Join-Path $WorkspaceRootDir 'script\cargo_build_profiles.jq' + $features = cargo metadata --format-version 1 --no-deps --locked --manifest-path "$WorkspaceRootDir\app\Cargo.toml" | + jq -er --arg profile_path $ProfilePath -f $jqFilter + if ($LASTEXITCODE -ne 0) { + throw "Failed to resolve Cargo build profile: $ProfilePath" + } + + return $features.Trim() +} if ($DEBUG_BUILD) { $CARGO_PROFILE = 'dev' @@ -96,12 +120,10 @@ if ("$CHANNEL" -eq 'local') { $WARP_BIN = 'dev' $BINARY_NAME = 'dev.exe' $APP_NAME = 'WarpDev' - $FEATURES = "$FEATURES,agent_mode_debug" } elseif ("$CHANNEL" -eq 'preview') { $WARP_BIN = 'preview' $BINARY_NAME = 'preview.exe' $APP_NAME = 'WarpPreview' - $FEATURES = "$FEATURES,preview_channel" } elseif ("$CHANNEL" -eq 'stable') { $WARP_BIN = 'stable' $BINARY_NAME = 'warp.exe' @@ -110,18 +132,13 @@ if ("$CHANNEL" -eq 'local') { $WARP_BIN = 'warp-oss' $BINARY_NAME = 'warp-oss.exe' $APP_NAME = 'WarpOss' - # The OSS channel does not ship Sentry, so drop the crash_reporting feature - # (which would otherwise pull in the Sentry SDK as a dependency). - $FEATURES = 'release_bundle,gui' } -if (("$CHANNEL" -eq 'local') -or ("$CHANNEL" -eq 'dev')) { - $FEATURES = "$FEATURES,nld_classifier_v3,nld_heuristic_v2" -} elseif ("$CHANNEL" -eq 'preview') { - $FEATURES = "$FEATURES,nld_classifier_v2,nld_heuristic_v2" -} else { - $FEATURES = "$FEATURES,nld_classifier_v1,nld_heuristic_v1" +$FEATURES = Resolve-CargoBundleFeatures -WorkspaceRootDir $WORKSPACE_ROOT_DIR -ProfilePath "windows.$CHANNEL.app" +if ($EXTRA_FEATURES) { + $FEATURES = "$FEATURES,$EXTRA_FEATURES" } +Write-Output "Using Cargo build profile windows.$CHANNEL.app with features: $FEATURES" $BINARY_PATH = "$CARGO_TARGET_OUTPUT_DIR\$BINARY_NAME" $BUNDLE_ID = "dev.warp.$APP_NAME"