1+ #! /bin/sh
2+ set -eu
3+
4+ # This script downloads the OS- and architecture-specific Kosli CLI binary,
5+ # extracts it, and moves the executable to a directory in your PATH.
6+
7+ # --- Configuration ---
8+ CLI_OS=" unknown"
9+ ARCH=" unknown"
10+ VERSION=" "
11+ FILE_NAME=" kosli"
12+ DEBUG=false
13+ GITHUB_TOKEN=" "
14+
15+ # --- Debug function ---
16+ debug_print () {
17+ if [ " $DEBUG " = true ]; then
18+ echo " DEBUG: $1 " >&2
19+ fi
20+ }
21+
22+ # --- Parse arguments ---
23+ while [ $# -gt 0 ]; do
24+ case $1 in
25+ --debug)
26+ DEBUG=true
27+ debug_print " Debug mode enabled"
28+ shift
29+ ;;
30+ --token)
31+ if [ -n " ${2:- } " ]; then
32+ GITHUB_TOKEN=" $2 "
33+ debug_print " GitHub token provided"
34+ shift 2
35+ else
36+ echo " Error: --token requires a value"
37+ exit 1
38+ fi
39+ ;;
40+ * )
41+ VERSION=$1
42+ debug_print " Version specified: $VERSION "
43+ shift
44+ ;;
45+ esac
46+ done
47+
48+ # --- Version Selection ---
49+ if [ -n " $VERSION " ]; then
50+ echo " Downloading specified version $VERSION of Kosli CLI..."
51+ debug_print " Using specified version: $VERSION "
52+ else
53+ echo " Detecting the latest version of Kosli CLI..."
54+ debug_print " Fetching latest version from GitHub API"
55+
56+ # Retry mechanism for fetching the latest version
57+ RETRY_COUNT=0
58+ MAX_RETRIES=5
59+ while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
60+ if [ -n " $GITHUB_TOKEN " ]; then
61+ debug_print " Using GitHub token for API request"
62+ METADATA=$( curl -s -H " Authorization: token $GITHUB_TOKEN " " https://api.github.com/repos/kosli-dev/cli/releases/latest" )
63+ else
64+ debug_print " Using unauthenticated API request"
65+ METADATA=$( curl -s " https://api.github.com/repos/kosli-dev/cli/releases/latest" )
66+ fi
67+ debug_print " GitHub API response: $METADATA "
68+
69+ # Check if the response contains the expected tag_name
70+ if echo " $METADATA " | grep -q ' "tag_name":' ; then
71+ TAG_NAME=$( echo " $METADATA " | grep ' "tag_name":' )
72+ debug_print " GitHub API response tag: $TAG_NAME "
73+ LATEST_TAG=$( echo " $TAG_NAME " | sed -E ' s/.*"([^"]+)".*/\1/' )
74+ debug_print " GitHub API response tag: $LATEST_TAG "
75+ if [ -z " $LATEST_TAG " ]; then
76+ echo " Error: Could not fetch the latest version tag from GitHub."
77+ exit 1
78+ fi
79+ VERSION=$LATEST_TAG
80+ echo " Latest version is $VERSION . Downloading..."
81+ debug_print " Set VERSION to: $VERSION "
82+ break
83+ else
84+ echo " Warning: GitHub API response did not contain a valid tag_name. Retrying in 5 seconds..."
85+ sleep 5
86+ RETRY_COUNT=$(( RETRY_COUNT + 1 ))
87+ if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
88+ echo " Error: GitHub rate limit exceeded too many times."
89+ exit 1
90+ fi
91+ fi
92+ done
93+ fi
94+ echo " "
95+
96+ # Strip the 'v' prefix for use in the filename, e.g., v2.11.22 -> 2.11.22
97+ VERSION_FILENAME=$( echo " $VERSION " | sed ' s/^v//' )
98+ debug_print " VERSION_FILENAME after stripping 'v': $VERSION_FILENAME "
99+
100+ # --- OS and Architecture Detection ---
101+ debug_print " Detecting OS and architecture"
102+ debug_print " uname -s output: $( uname -s) "
103+ debug_print " uname -m output: $( uname -m) "
104+
105+ UNAME_S=$( uname -s)
106+ if echo " $UNAME_S " | grep -q -E -i " (cygwin|mingw|msys|windows)" ; then
107+ CLI_OS=" windows"
108+ ARCH=" amd64"
109+ FILE_NAME=" ${FILE_NAME} .exe"
110+ debug_print " Detected Windows OS"
111+ elif echo " $UNAME_S " | grep -q -i " darwin" ; then
112+ CLI_OS=" darwin"
113+ debug_print " Detected Darwin/macOS"
114+ UNAME_M=$( uname -m)
115+ if [ " $UNAME_M " = " arm64" ]; then
116+ ARCH=" arm64"
117+ debug_print " Detected ARM64 architecture"
118+ else
119+ ARCH=" amd64"
120+ debug_print " Detected AMD64 architecture"
121+ fi
122+ else
123+ CLI_OS=" linux"
124+ debug_print " Detected Linux OS"
125+ MACHINE_TYPE=" $( uname -m) "
126+ debug_print " Machine type: $MACHINE_TYPE "
127+ case $MACHINE_TYPE in
128+ amd64 | x86_64 | x64)
129+ ARCH=" amd64"
130+ debug_print " Mapped to AMD64 architecture"
131+ ;;
132+ aarch64 | arm64)
133+ ARCH=" arm64"
134+ debug_print " Mapped to ARM64 architecture"
135+ ;;
136+ * )
137+ echo " Error: Unsupported Linux architecture: $MACHINE_TYPE "
138+ echo " Kosli CLI is only available for amd64 and arm64 on Linux."
139+ exit 1
140+ ;;
141+ esac
142+ fi
143+
144+ debug_print " Final values - CLI_OS: $CLI_OS , ARCH: $ARCH , FILE_NAME: $FILE_NAME "
145+
146+ # --- Download and Extract ---
147+ # The download is a .tar.gz or .zip file which needs to be extracted
148+ if [ " $CLI_OS " = " windows" ]; then
149+ URL=" https://github.com/kosli-dev/cli/releases/download/${VERSION} /kosli_${VERSION_FILENAME} _${CLI_OS} _${ARCH} .zip"
150+ debug_print " Windows URL constructed: $URL "
151+ echo " Downloading from: $URL "
152+ # Download and extract for Windows
153+ debug_print " Starting Windows download and extraction"
154+ if ! curl -L --fail " $URL " -o kosli.zip; then
155+ echo " Error: Download failed. Please check the URL and your network connection."
156+ exit 1
157+ fi
158+ debug_print " Download completed, extracting zip file"
159+ unzip -o kosli.zip
160+ debug_print " Extraction completed"
161+ else
162+ URL=" https://github.com/kosli-dev/cli/releases/download/${VERSION} /kosli_${VERSION_FILENAME} _${CLI_OS} _${ARCH} .tar.gz"
163+ debug_print " Unix URL constructed: $URL "
164+ echo " Downloading from: $URL "
165+ # Download and extract for Linux and Darwin
166+ debug_print " Starting Unix download and extraction"
167+ if ! curl -L --fail " $URL " | tar zx; then
168+ echo " Error: Download or extraction failed. Please check the URL and your network connection."
169+ exit 1
170+ fi
171+ debug_print " Download and extraction completed"
172+ fi
173+
174+ # --- Installation ---
175+ # Move the extracted binary to a directory in the user's PATH
176+ echo " Installing Kosli CLI..."
177+ debug_print " Starting installation process"
178+ debug_print " Current PATH: $PATH "
179+
180+ # Check directories one by one instead of using set --
181+ for dir in " /usr/local/bin" " /usr/bin" " /opt/bin" ; do
182+ debug_print " Checking directory: $dir "
183+ # Check if destination directory exists and is in the PATH
184+ if [ -d " $dir " ] && echo " $PATH " | grep -q " $dir " ; then
185+ debug_print " Directory $dir exists and is in PATH"
186+ debug_print " Attempting to move $FILE_NAME to $dir "
187+ if mv " $FILE_NAME " " $dir /" ; then
188+ echo " "
189+ echo " ✅ Kosli CLI was successfully installed in $dir "
190+ echo " Running 'kosli version' to verify:"
191+ debug_print " Installation successful, running version check"
192+ kosli version
193+ exit 0
194+ else
195+ echo " "
196+ echo " Attempting to install with sudo..."
197+ echo " We'd like to install the Kosli CLI executable in '$dir '. Please enter your password if prompted."
198+ debug_print " Regular move failed, trying with sudo"
199+ if sudo mv " $FILE_NAME " " $dir /" ; then
200+ echo " "
201+ echo " ✅ Kosli CLI was successfully installed in $dir "
202+ echo " Running 'kosli version' to verify:"
203+ debug_print " Sudo installation successful, running version check"
204+ kosli version
205+ exit 0
206+ fi
207+ debug_print " Sudo move also failed for $dir "
208+ fi
209+ else
210+ debug_print " Directory $dir either doesn't exist or is not in PATH"
211+ fi
212+ done
213+
214+ debug_print " All installation attempts failed"
215+ echo " "
216+ echo " Error: Could not install Kosli CLI."
217+ echo " Please move the '$FILE_NAME ' executable manually to a directory in your \$ PATH."
218+ echo " For example, you can run: sudo mv \" $FILE_NAME \" /usr/local/bin/"
219+ exit 1
0 commit comments