Skip to content

Commit 47e3f9b

Browse files
waveywavesclaude
andcommitted
fix: error when install script target directory does not exist
Add install.sh to the main repository (previously only in the now-archived chainloop-dev/docs repo) with the following improvements: 1. Add early validation after argument parsing to verify the --path installation directory exists before downloading anything. Provides a clear error message with a suggested fix (mkdir -p) instead of failing silently or showing confusing sudo errors. 2. Improve the install step to provide proper error output when the binary installation fails, instead of silently redirecting stderr to /dev/null. Fixes #2977 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Vibhav Bobade <vibhav.bobde@gmail.com>
1 parent b200376 commit 47e3f9b

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

install.sh

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Based on https://developer.fermyon.com/ install script thanks!
5+
# Fancy colors for output
6+
RED='\033[0;31m'
7+
GREEN='\033[0;32m'
8+
NC='\033[0m' # No Color aka reset
9+
10+
# Version to install. Defaults to latest or set by --version or -v
11+
VERSION=""
12+
FORCE_VERIFICATION=false
13+
INSTALL_PATH=/usr/local/bin
14+
PUBLIC_KEY_URL="https://raw.githubusercontent.com/chainloop-dev/docs/c5b7b9be051d8d3b9f48153c6e3ccf569e6990e8/static/cosign-releases.pub"
15+
16+
# Print in colors - 0=green, 1=red, 2=neutral
17+
# e.g. fancy_print 0 "All is great"
18+
fancy_print() {
19+
if [[ $1 == 0 ]]; then
20+
echo -e "${GREEN}${2}${NC}"
21+
elif [[ $1 == 1 ]]; then
22+
echo -e "${RED}${2}${NC}"
23+
else
24+
echo -e "${2}"
25+
fi
26+
}
27+
28+
29+
# Function to print the help message
30+
print_help() {
31+
fancy_print 2 ""
32+
fancy_print 2 "---- Chainloop Installer Script ----"
33+
fancy_print 2 "This script installs Chainloop in the current directory."
34+
fancy_print 2 ""
35+
fancy_print 2 "Command line arguments"
36+
fancy_print 2 "--version or -v Provide what version to install e.g. \"v0.5.0\"."
37+
fancy_print 2 "--path Installation path (default: /usr/local/bin)"
38+
fancy_print 2 "--force-verification Force signature verification of the binary with cosign."
39+
fancy_print 2 "--help or -h Shows this help message"
40+
}
41+
42+
# Function used to check if utilities are available
43+
require() {
44+
if ! hash "$1" &>/dev/null; then
45+
fancy_print 1 "'$1' not found in PATH. This is required for this script to work."
46+
exit 1
47+
fi
48+
}
49+
50+
# check if a command exist
51+
is_command() {
52+
command -v "$1" >/dev/null
53+
}
54+
55+
# checksums.txt file validation
56+
# example: check_sha256 "${TMP_DIR}" checksums.txt
57+
validate_checksums_file() {
58+
cd "$1"
59+
if is_command sha256sum; then
60+
sha256sum --ignore-missing --quiet --check "$2"
61+
elif is_command shasum; then
62+
shasum -a 256 --ignore-missing --quiet --check checksums.txt
63+
else
64+
fancy_print 1 "We were not able to verify checksums. Commands sha256sum, shasum are not found."
65+
return 1
66+
fi
67+
fancy_print 2 "Checksum OK\n"
68+
}
69+
70+
# Parse input arguments
71+
while [[ $# -gt 0 ]]; do
72+
case $1 in
73+
'--version' | -v)
74+
shift
75+
if [[ $# -ne 0 ]]; then
76+
# Remove v prefix if provided
77+
VERSION="$(echo ${1} | sed -e 's/^v\(.*\)/\1/')"
78+
else
79+
fancy_print 1 "Please provide the desired version. e.g. --version v0.5.0"
80+
exit 0
81+
fi
82+
;;
83+
'--help' | -h)
84+
shift
85+
print_help
86+
;;
87+
'--force-verification')
88+
FORCE_VERIFICATION=true
89+
;;
90+
'--path')
91+
shift
92+
INSTALL_PATH=$1
93+
;;
94+
*)
95+
fancy_print 1 "Unknown argument ${1}."
96+
print_help
97+
exit 1
98+
;;
99+
esac
100+
shift
101+
done
102+
103+
# Validate that the installation path exists
104+
if [ ! -d "${INSTALL_PATH}" ]; then
105+
fancy_print 1 "The installation path '${INSTALL_PATH}' does not exist. Please create it first with: mkdir -p ${INSTALL_PATH}"
106+
exit 1
107+
fi
108+
109+
# Check all required utilities are available
110+
require curl
111+
require tar
112+
require uname
113+
114+
if ! hash "cosign" &>/dev/null; then
115+
if [[ $FORCE_VERIFICATION = true ]]; then
116+
fancy_print 1 "--force-verification was set but Cosign is not present. Please download it from here https://docs.sigstore.dev/cosign/installation"
117+
exit 1
118+
fi
119+
fi
120+
121+
# Check if we're on a supported system and get OS and processor architecture to download the right version
122+
UNAME_ARC=$(uname -m)
123+
124+
case $UNAME_ARC in
125+
"x86_64")
126+
ARC="amd64"
127+
;;
128+
"arm64"|"aarch64")
129+
ARC="arm64"
130+
;;
131+
*)
132+
fancy_print 1 "The Processor type: ${UNAME_ARC} is not yet supported by Chainloop."
133+
exit 1
134+
;;
135+
esac
136+
137+
case $OSTYPE in
138+
"linux-gnu"*)
139+
OS="linux"
140+
;;
141+
"darwin"*)
142+
OS="darwin"
143+
;;
144+
*)
145+
fancy_print 1 "The OSTYPE: ${OSTYPE} is not supported by this script."
146+
exit 1
147+
;;
148+
esac
149+
150+
# Check desired version. Default to latest if no desired version was requested
151+
if [[ $VERSION = "" ]]; then
152+
VERSION=$(curl -so- https://github.com/chainloop-dev/chainloop/releases | grep 'href="/chainloop-dev/chainloop/releases/tag/v[0-9]*.[0-9]*.[0-9]*\"' | sed -E 's/.*\/chainloop-dev\/chainloop\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1)
153+
# Remove v prefix
154+
VERSION="$(echo ${VERSION} | sed -e 's/^v\(.*\)/\1/')"
155+
fi
156+
157+
# Temporary directory, works on Linux and macOS
158+
TMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
159+
FILENAME="chainloop-cli-${VERSION}-${OS}-${ARC}.tar.gz"
160+
# Constructing download FILE and URL
161+
FILE="${TMP_DIR}/${FILENAME}"
162+
163+
BASE_URL="https://github.com/chainloop-dev/chainloop/releases/download/v${VERSION}"
164+
165+
URL="${BASE_URL}/${FILENAME}"
166+
# Download file, exit if not found - e.g. version does not exist
167+
fancy_print 0 "Step 1: Downloading: ${FILENAME}"
168+
curl -fsL $URL -o $FILE || (fancy_print 1 "The requested file does not exist: ${URL}"; exit 1)
169+
fancy_print 0 "Done...\n"
170+
171+
# Get checksum file and check it
172+
fancy_print 0 "Step 1.2: Verifying checksum"
173+
CHECKSUM_FILENAME=checksums.txt
174+
CHECKSUM_FILE="${TMP_DIR}/${CHECKSUM_FILENAME}"
175+
URL="${BASE_URL}/${CHECKSUM_FILENAME}"
176+
curl -fsL $URL -o ${CHECKSUM_FILE} || (fancy_print 1 "The requested file does not exist: ${URL}"; exit 1)
177+
validate_checksums_file "${TMP_DIR}" checksums.txt
178+
179+
# Verify checksum file signature
180+
if hash "cosign" &>/dev/null; then
181+
# Constructing download FILE and URL
182+
SIGNATURE_FILE="${CHECKSUM_FILENAME}.sig"
183+
URL="${BASE_URL}/${SIGNATURE_FILE}"
184+
# Download file, exit if not found - e.g. version does not exist
185+
fancy_print 0 "Step 1.3: Verifying signature"
186+
curl -fsOL $URL || (fancy_print 1 "The requested file does not exist: ${SIGNATURE_FILE}"; exit 1)
187+
cosign verify-blob \
188+
--key ${PUBLIC_KEY_URL} \
189+
--signature ${SIGNATURE_FILE} \
190+
${CHECKSUM_FILE}
191+
192+
rm $SIGNATURE_FILE
193+
else
194+
fancy_print 2 "\nSignature verification skipped, cosign is not installed\n"
195+
fi
196+
197+
# Decompress the file
198+
fancy_print 0 "Step 2: Decompressing: ${FILE}"
199+
BINARY_NAME="chainloop"
200+
BINARY="${TMP_DIR}/chainloop"
201+
(cd ${TMP_DIR} && tar xf $FILE)
202+
fancy_print 0 "Done...\n"
203+
204+
# Install
205+
fancy_print 0 "Step 3: Installing: ${BINARY_NAME} in path ${INSTALL_PATH}"
206+
if ! install "${BINARY}" "${INSTALL_PATH}/" 2>/tmp/chainloop_install_err; then
207+
fancy_print 2 "Install without sudo failed, trying with sudo..."
208+
if ! sudo install "${BINARY}" "${INSTALL_PATH}/"; then
209+
fancy_print 1 "Failed to install '${BINARY_NAME}' to '${INSTALL_PATH}/'. Please check permissions."
210+
cat /tmp/chainloop_install_err 2>/dev/null
211+
rm -f /tmp/chainloop_install_err
212+
exit 1
213+
fi
214+
fi
215+
rm -f /tmp/chainloop_install_err
216+
217+
# Remove the compressed file
218+
fancy_print 0 "Step 4: Cleanup"
219+
rm -r ${TMP_DIR}
220+
fancy_print 0 "Done...\n"
221+
${INSTALL_PATH}/${BINARY_NAME} version
222+
223+
224+
fancy_print 2 "Check here for the next steps: https://docs.chainloop.dev\n"
225+
fancy_print 2 "Run '${BINARY_NAME} auth login' to get started"

0 commit comments

Comments
 (0)