#!/usr/bin/env bash ## ## ## ## ## : WARNING: This Genkit CLI install script is still in active development. Do not use outside of testing and providing feedback. : ========================================== : Introduction : ========================================== # This script allows you to install the latest version of the # "genkit" command by running: # : curl -sL cli.genkit.dev | bash # # If you do not want to use this script, you can manually # download the latest "genkit" binary. # : curl -Lo ./genkit_bin https://storage.googleapis.com/genkit-assets-cli/prod/linux-x64/latest # # Alternatively, you can download a specific version. # : curl -Lo ./genkit_bin https://storage.googleapis.com/genkit-assets-cli/prod/linux-x64/v1.15.5/genkit # # For Windows append ".exe" to the URL. # : curl -Lo ./genkit_bin https://storage.googleapis.com/genkit-assets-cli/prod/win32-x64/v1.15.5/genkit.exe # # Note: On Mac, replace "linux" with "darwin" in the URL. # Supported architectures: darwin-x64, darwin-arm64, linux-x64, linux-arm64, win32-x64 # # For full details about installation options for the Genkit CLI # please see our documentation. # https://genkit.dev # # Please report bugs / issues with this script on GitHub. # https://github.com/firebase/genkit # : ========================================== : Advanced Usage : ========================================== # The behavior of this script can be modified at runtime by passing environmental # variables to the `bash` process. # # For curl execution (environment variables): # : curl -sL cli.genkit.dev | arg1=true arg2=false bash # # These arguments are optional, but be aware that explicitly setting them will help # ensure consistent behavior if / when defaults are changed. # : ----------------------------------------- : Upgrading - default: false : ----------------------------------------- # By default, this script will not replace an existing "genkit" install. # If you'd like to upgrade an existing install, use the upgrade option. # # Curl execution: : curl -sL cli.genkit.dev | upgrade=true bash # # This operation could (potentially) break an existing install, so use it with caution. # : ----------------------------------------- : Uninstalling - default false : ----------------------------------------- # You can remove the binary by passing the "uninstall" flag. # # Curl execution: : curl -sL cli.genkit.dev | uninstall=true bash # # This will remove the binary file and any cached data. # : ----------------------------------------- : Local install switch : ----------------------------------------- # To force a user-local install into $HOME/.local/bin (useful on systems without sudo), # you can pass the following: # : curl -sL cli.genkit.dev | local=true bash # # You can also explicitly set a target path: # : curl -sL cli.genkit.dev | GENKIT_BINARY="$HOME/.local/bin/genkit" bash # : ----------------------------------------- : Analytics - default true : ----------------------------------------- # This script reports anonymous success / failure analytics. # You can disable this reporting by setting the "analytics" variable to false. # # Curl execution: : curl -sL cli.genkit.dev | analytics=false bash # # By default we report all data anonymously and do not collect any information # except platform type (Darwin, Win, etc) in the case of an unsupported platform # error. # : ========================================== : Source Code : ========================================== # Options: prod, next channel="${channel:-prod}" # This script contains a large amount of comments so you can understand # how it interacts with your system. If you're not interested in the # technical details, you can just run the command above. # We begin by generating a unique ID for tracking the anonymous session. CID=$(head -80 /dev/urandom | LC_ALL=c tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) # Credit: https://gist.github.com/earthgecko/3089509 # We can use this CID in all calls to the Google Analytics endpoint via # this reusable function. TRACKING_ID="G-VE2GNRL789" send_analytics_event() { if [ ! "$analytics" = "false" ]; then curl -s https://www.google-analytics.com/collect \ -d "tid=$TRACKING_ID" \ -d "t=event" \ -d "ec=cli.genkit.dev" \ -d "ea=$1" \ -d "v=1" \ -d "cid=$CID" \ -o /dev/null fi # For now, just return success return 0 } # We send one event to count the number of times this script is ran. At the # end we also report success / failure, but it's possible that the script # will crash before we get to that point, so we manually count invocations here. send_analytics_event start # Debug/verbosity: where to send stderr for version probes if [ -n "${DEBUG-}" ] && [ "$DEBUG" != "0" ]; then VERBOSE_STDERR="/dev/stderr" else VERBOSE_STDERR="/dev/null" fi # Helper: check whether sudo exists *and* is usable (non-interactive). has_usable_sudo() { if command -v sudo >/dev/null 2>&1; then sudo -n true >/dev/null 2>&1 || return 1 return 0 fi return 1 } # Helper: get effective UID in shells where $EUID may not be set. get_euid() { if [ -n "${EUID-}" ]; then printf '%s' "$EUID" else id -u fi } # Capture any user-provided desired install target, but keep detection separate. DESIRED_BINARY="$GENKIT_BINARY" # Explicit local-install switch. if [ "${local:-}" = "true" ]; then DESIRED_BINARY="$HOME/.local/bin/genkit" fi # We try to detect any existing binaries on $PATH or two common locations. EXISTING_BINARY="$(command -v genkit 2>/dev/null)" LOCAL_BINARY="$HOME/.local/bin/genkit" # For info about why we place the binary at this location, see # https://unix.stackexchange.com/a/8658 GLOBAL_BINARY="/usr/local/bin/genkit" if [[ -z "$EXISTING_BINARY" ]]; then if [ -e "$LOCAL_BINARY" ]; then EXISTING_BINARY="$LOCAL_BINARY" elif [ -e "$GLOBAL_BINARY" ]; then EXISTING_BINARY="$GLOBAL_BINARY" fi fi # If the user asked for us to uninstall genkit, then do so. if [ "$uninstall" = "true" ]; then if [[ -z "$DESIRED_BINARY" ]]; then TARGET="$EXISTING_BINARY" else TARGET="$DESIRED_BINARY" fi if [ -z "$TARGET" ]; then echo "Cannot detect any Genkit CLI installations." echo "Please manually remove any \"genkit\" binaries not in \$PATH." else echo "-- Removing binary file: $TARGET" uninstall_sudo="" uninstall_dir="$(dirname -- "$TARGET")" euid="$(get_euid)" if [ "$euid" -ne 0 ] && [ ! -w "$uninstall_dir" ] && has_usable_sudo; then uninstall_sudo="sudo" fi $uninstall_sudo rm -f -- "$TARGET" 2>/dev/null || true fi echo "-- Removing genkit cache..." rm -rf ~/.cache/genkit echo "-- genkit has been uninstalled" echo "-- All Done!" send_analytics_event uninstall exit 0 fi # We need to ensure that we don't mess up an existing "genkit" # install, so before doing anything we check to see if this system # has "genkit" installed and if so, we exit out. echo "-- Checking for existing genkit installation..." if [[ ! -z "$EXISTING_BINARY" ]]; then # Only treat as installed if the detected binary actually exists and is executable if [ -x "$EXISTING_BINARY" ]; then INSTALLED_GENKIT_VERSION=$("$EXISTING_BINARY" --version 2>"$VERBOSE_STDERR") else INSTALLED_GENKIT_VERSION="" fi # In the case of a corrupt genkit install, we wont be able to # retrieve a version number, so to keep the logs correct, we refer to # your existing install as either the CLI version or as a "corrupt install" if [[ ! -z "$INSTALLED_GENKIT_VERSION" ]]; then GENKIT_NICKNAME="genkit@$INSTALLED_GENKIT_VERSION" else GENKIT_NICKNAME="a corrupted genkit binary" fi # Skip npm check - assume binary install # If the user didn't pass upgrade=true, then we print the command to do an upgrade and exit if [ ! "$upgrade" = "true" ]; then echo "Your machine has $GENKIT_NICKNAME installed." echo "If you would like to upgrade your install run: curl -sL cli.genkit.dev | upgrade=true bash" send_analytics_event already_installed exit 0 else # If the user did pass upgrade=true, then we allow the script to continue and overwrite the install. echo "-- Your machine has $GENKIT_NICKNAME, attempting upgrade..." send_analytics_event upgrade fi fi echo "-- Checking your machine type..." # Now we need to detect the platform we're running on (Linux / Mac / Other) # so we can fetch the correct binary and place it in the correct location # on the machine. # We use "tr" to translate the uppercase "uname" output into lowercase UNAME=$(uname -s | tr '[:upper:]' '[:lower:]') # Detect architecture ARCH=$(uname -m) case "$ARCH" in x86_64) ARCH_SUFFIX="x64";; aarch64|arm64) ARCH_SUFFIX="arm64";; *) ARCH_SUFFIX="x64";; # Default to x64 esac # Then we map the output to the names used on the GitHub releases page case "$UNAME" in linux*) MACHINE="linux-${ARCH_SUFFIX}";; darwin*) MACHINE="darwin-${ARCH_SUFFIX}";; mingw*|msys*|cygwin*) MACHINE="win32-x64";; esac # If we never define the $MACHINE variable (because our platform is neither Mac, # Linux, or Windows), then we can't finish our job, so just log out a helpful message # and close. if [[ -z "$MACHINE" ]]; then echo "Your operating system is not supported, if you think it should be please file a bug." echo "https://github.com/firebase/genkit/" echo "-- All done!" send_analytics_event "missing_platform_${UNAME}_${ARCH}" exit 0 fi # We have enough information to generate the binary's download URL. DOWNLOAD_URL="https://storage.googleapis.com/genkit-assets-cli/$channel/$MACHINE/latest" echo "-- Downloading binary from $DOWNLOAD_URL" # We use "curl" to download the binary with a flag set to follow redirects # (GitHub download URLs redirect to CDNs) and a flag to show a progress bar. curl -o "/tmp/genkit_standalone.tmp" --fail -L --progress-bar "$DOWNLOAD_URL" if [ $? -ne 0 ]; then echo "Something went wrong. Failed to download binary from $DOWNLOAD_URL" echo "Please file a bug with your system information on GitHub." echo "https://github.com/firebase/genkit/" send_analytics_event download_failure exit 1 fi # Determine install target: prefer user-provided location, otherwise global default. GENKIT_BINARY=${DESIRED_BINARY:-$GLOBAL_BINARY} INSTALL_DIR=$(dirname -- "$GENKIT_BINARY") # We need to ensure that the INSTALL_DIR exists. # On some platforms like the Windows Subsystem for Linux it may not. # We created it using a non-destructive mkdir command. mkdir -p -- "$INSTALL_DIR" 2> /dev/null # If the directory does not exist or is not writable, we resort to sudo when available and usable. sudo_cmd="" if [ ! -w "$INSTALL_DIR" ]; then euid="$(get_euid)" if [ "$euid" -eq 0 ]; then sudo_cmd="" # already root elif has_usable_sudo; then sudo_cmd="sudo" else echo "-- '$INSTALL_DIR' is not writable and 'sudo' is not available; falling back to a user-local install." GENKIT_BINARY="$LOCAL_BINARY" INSTALL_DIR=$(dirname -- "$GENKIT_BINARY") mkdir -p -- "$INSTALL_DIR" 2> /dev/null sudo_cmd="" fi fi $sudo_cmd mkdir -p -- "$INSTALL_DIR" $sudo_cmd mv -f "/tmp/genkit_standalone.tmp" "$GENKIT_BINARY" # Once the download is complete, we mark the binary file as readable # and executable (+rx). echo "-- Setting permissions on binary... $GENKIT_BINARY" $sudo_cmd chmod +rx "$GENKIT_BINARY" # If all went well, the "genkit" binary should be located on our PATH so # we'll run it once, asking it to print out the version. This is helpful as # standalone genkit binaries do a small amount of setup on the initial run # so this not only allows us to make sure we got the right version, but it # also does the setup so the first time the developer runs the binary, it'll # be faster. VERSION=$("$GENKIT_BINARY" --version 2>"$VERBOSE_STDERR") # If no version is detected then clearly the binary failed to install for # some reason, so we'll log out an error message and report the failure # to headquarters via an analytics event. if [[ -z "$VERSION" ]]; then echo "Something went wrong, genkit has not been installed." echo "Please file a bug with your system information on GitHub." echo "https://github.com/firebase/genkit/" echo "-- All done!" send_analytics_event binary_check_failure exit 1 fi # In order for the user to be able to actually run the "genkit" command # without specifying the absolute location, the INSTALL_DIR path must # be present inside of the PATH environment variable. echo "-- Checking your PATH variable..." case ":$PATH:" in *":$INSTALL_DIR:"*) : ;; *) echo "" echo "It looks like $INSTALL_DIR isn't on your PATH." if [ "$INSTALL_DIR" = "$HOME/.local/bin" ]; then echo "Heads up: many distros expect user-local binaries in \$HOME/.local/bin." fi echo "Please add the following line to either your ~/.profile or ~/.bash_profile, then restart your terminal." echo "" echo "export PATH=\"$INSTALL_DIR:\$PATH\"" echo "" echo "For more information about modifying PATHs, see https://unix.stackexchange.com/a/26059" echo "" send_analytics_event missing_path ;; esac # We also try to upgrade the local binary if it exists. # This helps prevent having two mismatching versions of "genkit". if [[ "$GENKIT_BINARY" != "$LOCAL_BINARY" ]] && [ -e "$LOCAL_BINARY" ]; then echo "-- Upgrading the local binary installation $LOCAL_BINARY..." cp "$GENKIT_BINARY" "$LOCAL_BINARY" 2>/dev/null || true # best effort, okay if it fails. chmod +x "$LOCAL_BINARY" 2>/dev/null || true fi # Since we've gotten this far we know everything succeeded. We'll just # let the developer know everything is ready and take our leave. echo "-- genkit@$VERSION is now installed" echo "-- All Done!" send_analytics_event success exit 0 # ------------------------------------------ # Notes # ------------------------------------------ # # This script contains hidden JavaScript which is used to improve # readability in the browser (via syntax highlighting, etc), right-click # and "View source" of this page to see the entire bash script! # # You'll also notice that we use the ":" character in the Introduction # which allows our copy/paste commands to be syntax highlighted, but not # ran. In bash : is equal to `true` and true can take infinite arguments # while still returning true. This turns these commands into no-ops so # when ran as a script, they're totally ignored. #