Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ on:
branches:
- "**"
paths:
- '.github/workflows/install.yml'
- 'src/bin/install'
- ".github/workflows/install.yml"
- "src/bin/install"

jobs:
install:
Expand All @@ -31,3 +31,9 @@ jobs:

- name: Sanity check
run: defang --version

- name: Install with bash (nightly)
shell: bash
run: bash <(curl -fsSL s.defang.io/install) nightly
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # alt name
100 changes: 67 additions & 33 deletions src/bin/install
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/bin/sh
#######################################################################################
# #
# This script installs the latest release of Defang from GitHub. It is designed #
Expand All @@ -8,8 +9,21 @@
# This allows us to do some interactive stuff where we can prompt the user for input #
# and have the user run the defang executable from the updated PATH environment var. #
# #
# Pin to a specific version using DEFANG_INSTALL_VERSION or: #
# #
# bash <(curl -fsSL s.defang.io/install) 3.5.2 #
# curl -fsSL s.defang.io/install | sh -s -- v3.5.2 #
# curl -fsSL s.defang.io/install | bash -s -- nightly #
# #
#######################################################################################

_defang_install() {
local REPLY CI="${CI:-}"
local RELEASE_PATH AUTH_HEADER RELEASE_JSON
local ARCH OS ARCH_SUFFIX DOWNLOAD_URL FILENAME EXTRACT_DIR
local INSTALL_DIR="${INSTALL_DIR:-}" BINARY_NAME
local EXPORT_PATH FOUND_PROFILE_FILE CURRENT_SHELL

echo "\
__ ____
____/ /__ / __/___ _____ ____ _
Expand All @@ -19,16 +33,26 @@ echo "\
/____/
"

# Check for -y flag or CI var and set the REPLY variable to "y" if it is present
if [[ "$1" == "-y" ]] || [[ "$CI" == "1" ]] || [[ "$CI" == "true" ]]; then
REPLY="y" # TODO: this will fail in Fish shell
# Parse arguments: [-y] [version]
for _arg in "$@"; do
if [ "$_arg" = "-y" ]; then
REPLY="y"
CI="1"
elif [ -z "$DEFANG_INSTALL_VERSION" ]; then
DEFANG_INSTALL_VERSION="$_arg"
fi
done
Comment thread
lionello marked this conversation as resolved.
unset _arg

if [ "$CI" = "1" ] || [ "$CI" = "true" ]; then
REPLY="y"
CI="1"
fi

# check if DEFANG_INSTALL_VERSION is set and set the release path accordingly
if [[ -z "$DEFANG_INSTALL_VERSION" ]]; then
if [ -z "$DEFANG_INSTALL_VERSION" ]; then
RELEASE_PATH="latest"
elif [[ "$DEFANG_INSTALL_VERSION" == "nightly" ]]; then
elif [ "$DEFANG_INSTALL_VERSION" = "nightly" ]; then
RELEASE_PATH="tags/nightly"
else
RELEASE_PATH="tags/v${DEFANG_INSTALL_VERSION#v}"
Expand All @@ -37,16 +61,16 @@ fi
# Anonymous API request to GitHub are rate limited to 60 requests per hour.
# Check whether the user has set a GitHub token to increase the rate limit.
AUTH_HEADER=""
if [[ -n "$GITHUB_TOKEN" ]]; then
if [ -n "$GITHUB_TOKEN" ]; then
AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN"
elif [[ -n "$GH_TOKEN" ]]; then
elif [ -n "$GH_TOKEN" ]; then
AUTH_HEADER="Authorization: Bearer $GH_TOKEN"
fi

# Echo fetching the release path either latest or the version
echo "Fetching the ${RELEASE_PATH#tags/} release of defang..."
# Download the release information from GitHub, using the token if available, but falling back to anonymous access
RELEASE_JSON=$([[ -n "$AUTH_HEADER" ]] &&
RELEASE_JSON=$([ -n "$AUTH_HEADER" ] &&
curl -fsSL -H "$AUTH_HEADER" https://api.github.com/repos/DefangLabs/defang/releases/$RELEASE_PATH ||
curl -fsSL https://api.github.com/repos/DefangLabs/defang/releases/$RELEASE_PATH)

Expand Down Expand Up @@ -177,27 +201,32 @@ _prompt_and_append_to_file() {
echo
echo " $line"
echo
if [[ "$CI" != "1" ]]; then
if [ "$CI" != "1" ]; then
# Prompt the user for confirmation
echo -n "$prompt $profile_file? (y/n) "
printf "%s %s? (y/n) " "$prompt" "$profile_file"
read REPLY
echo # move to a new line
fi
if [[ $REPLY =~ ^[Yy]$ ]]; then
# Append the line to the profile file
echo >> "$profile_file"
echo "$line # Added by Defang install" >> "$profile_file"
else
# Print the command for the user to run manually
echo "To manually add the required line, run the following command:"
echo
echo " echo '$line' >> \"$profile_file\""
echo
fi
case "$REPLY" in
[Yy])
# Append the line to the profile file
echo >> "$profile_file"
echo "$line # Added by Defang install" >> "$profile_file"
;;
*)
# Print the command for the user to run manually
echo "To manually add the required line, run the following command:"
echo
echo " echo '$line' >> \"$profile_file\""
echo
;;
esac
}

# Add the installation directory to PATH if not already present
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
case ":$PATH:" in
*":$INSTALL_DIR:"*) ;;
*)
echo "Adding $INSTALL_DIR to your PATH for this session."
export PATH="$PATH:$INSTALL_DIR"

Expand All @@ -208,20 +237,21 @@ if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
FOUND_PROFILE_FILE=false
for CURRENT_SHELL in bash zsh ksh; do
# If the profile file exists in the user's home directory, add a line to it
if [[ -f "$HOME/.${CURRENT_SHELL}rc" ]]; then
if [ -f "$HOME/.${CURRENT_SHELL}rc" ]; then
FOUND_PROFILE_FILE=true
_prompt_and_append_to_file "Can we append the necessary line to" "$HOME/.${CURRENT_SHELL}rc" "$EXPORT_PATH"
fi
done

# If no profile file was found
if [[ $FOUND_PROFILE_FILE == false ]]; then
if [ "$FOUND_PROFILE_FILE" = false ]; then
# Get the name of the current shell
CURRENT_SHELL="$(basename "${SHELL:-$0}")"
# Prompt the user to create a new profile file
_prompt_and_append_to_file "No existing profile file found. Can we create" "$HOME/.${CURRENT_SHELL}rc" "$EXPORT_PATH"
fi
fi
;;
esac

# Usage: _generate_completion_script "shell" "path/to/completion/_script"
_generate_completion_script() {
Expand All @@ -239,25 +269,26 @@ _install_completion_script() {
case $shell in
bash)
_generate_completion_script $shell "$HOME/.local/share/bash-completion.d/defang" || return 11
if [[ -z "$BASH_COMPLETION_VERSINFO" ]]; then
if [ -z "$BASH_COMPLETION_VERSINFO" ]; then
echo "Warning: bash completions require package bash-completion to be installed."
return 14
fi
Comment thread
lionello marked this conversation as resolved.
_prompt_and_append_to_file "Can we add shell completions to" "$HOME/$profile_file" "source \$HOME/.local/share/bash-completion.d/defang"
;;
zsh)
_generate_completion_script $shell "$HOME/.local/share/zsh/site-functions/_defang" || return 12
if [[ ":$FPATH:" != *":$HOME/.local/share/zsh/site_functions:"* ]]; then
_prompt_and_append_to_file "Can we add shell completions to" "$HOME/$profile_file" "fpath=(\$HOME/.local/share/zsh/site-functions \$fpath)"
fi
case ":$FPATH:" in
*":$HOME/.local/share/zsh/site-functions:"*) ;;
*) _prompt_and_append_to_file "Can we add shell completions to" "$HOME/$profile_file" "fpath=(\$HOME/.local/share/zsh/site-functions \$fpath)" ;;
esac
Comment thread
lionello marked this conversation as resolved.
;;
*) return 13 ;;
esac
}

_install_completion_script $SHELL || true
CURRENT_SHELL=${0#-}
[[ $CURRENT_SHELL != $SHELL ]] && _install_completion_script $CURRENT_SHELL || true
[ "$CURRENT_SHELL" != "$SHELL" ] && _install_completion_script $CURRENT_SHELL || true

# Cleanup: Remove the temporary directory
echo "Cleaning up..."
Expand All @@ -273,6 +304,9 @@ if [ -t 1 ] && [ "$CI" != "1" ] && [ "$CI" != "true" ]; then
echo "Alternatively, you can use Defang's built-in agent by running '$BINARY_NAME'."
fi

# Unset the variables and functions to avoid polluting the user's environment
unset EXTRACT_DIR DOWNLOAD_URL RELEASE_JSON RELEASE_PATH ARCH_SUFFIX ARCH OS FILENAME INSTALL_DIR BINARY_NAME REPLY EXPORT_PATH CURRENT_SHELL FOUND_PROFILE_FILE AUTH_HEADER
unset -f _prompt_and_append_to_file _generate_completion_script _install_completion_script
}

_defang_install "$@"

# Unset functions to avoid polluting the user's environment when sourcing the script
unset -f _defang_install _prompt_and_append_to_file _generate_completion_script _install_completion_script 2>/dev/null
Loading