Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·160 lines (144 loc) · 5.85 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·160 lines (144 loc) · 5.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/bin/sh
# Install the skilld CLI without Node.js.
#
# curl -fsSL https://skilld.dev/install.sh | sh
#
# Environment:
# SKILLD_INSTALL_DIR Install directory. Default: $HOME/.skilld/bin
# SKILLD_VERSION Exact version to install, for example 3.1.0. Default: latest
# SKILLD_NO_MODIFY_PATH=1 Leave shell profiles alone. Default: add the install
# directory to PATH in the profile for $SHELL
#
# The installed CLI upgrades itself after it verifies each signed release.
set -eu
RELEASE_PUBLIC_KEY="__SKILLD_RELEASE_PUBLIC_KEY__"
REPOSITORY="https://github.com/skilld-dev/skilld"
fail() {
printf 'skilld install: %s\n' "$1" >&2
exit 1
}
download() {
if command -v curl >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -fsSL "$1" -o "$2"
elif command -v wget >/dev/null 2>&1; then
wget --https-only -q "$1" -O "$2"
else
fail "Install curl or wget, then run this script again."
fi
}
sha256() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" | awk '{print $1}'
elif command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$1" | awk '{print $1}'
else
fail "Install sha256sum or shasum, then run this script again."
fi
}
base64url_decode() {
value=$(printf '%s' "$1" | tr '_-' '/+')
case $((${#value} % 4)) in
2) value="$value==" ;;
3) value="$value=" ;;
esac
printf '%s' "$value" | openssl base64 -d -A
}
# Verifies the release manifest signature when OpenSSL supports Ed25519.
# Returns 2 when this system cannot check the signature.
verify_signature() {
case "$RELEASE_PUBLIC_KEY" in __*) return 2 ;; esac
command -v openssl >/dev/null 2>&1 || return 2
# DER SubjectPublicKeyInfo for a raw Ed25519 key.
printf '\060\052\060\005\006\003\053\145\160\003\041\000' >"$work/key.der"
base64url_decode "$RELEASE_PUBLIC_KEY" >>"$work/key.der" || return 2
openssl pkey -pubin -inform DER -in "$work/key.der" -out "$work/key.pem" >/dev/null 2>&1 || return 2
printf 'skilld-release-v1\000' >"$work/message"
openssl dgst -sha256 -binary "$work/skilld-release.txt" >>"$work/message" || return 2
base64url_decode "$(tr -d '\n' <"$work/skilld-release.sig")" >"$work/signature" || return 1
openssl pkeyutl -verify -pubin -inkey "$work/key.pem" -rawin \
-in "$work/message" -sigfile "$work/signature" >/dev/null 2>&1 && return 0
# Distinguish a bad signature from an OpenSSL without Ed25519 support.
openssl pkeyutl -help 2>&1 | grep -q -- '-rawin' || return 2
return 1
}
case "$(uname -s)" in
Linux) os=linux ;;
Darwin) os=darwin ;;
*) fail "This script supports Linux and macOS. On Windows, run install.ps1." ;;
esac
case "$(uname -m)" in
x86_64 | amd64) arch=x64 ;;
arm64 | aarch64) arch=arm64 ;;
*) fail "skilld has no build for $(uname -m)." ;;
esac
if [ "$os" = darwin ]; then
asset="skilld-cli-darwin-$arch"
else
libc=gnu
if ls /lib/ld-musl-* >/dev/null 2>&1 || (ldd --version 2>&1 | grep -qi musl); then
libc=musl
fi
asset="skilld-cli-linux-$arch-$libc"
fi
if [ -n "${SKILLD_VERSION:-}" ]; then
release="$REPOSITORY/releases/download/v$SKILLD_VERSION"
else
release="$REPOSITORY/releases/latest/download"
fi
install_dir="${SKILLD_INSTALL_DIR:-$HOME/.skilld/bin}"
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT INT TERM
download "$release/skilld-release.txt" "$work/skilld-release.txt"
download "$release/skilld-release.sig" "$work/skilld-release.sig"
set +e
verify_signature
signature_status=$?
set -e
case $signature_status in
0) ;;
2) printf 'skilld install: OpenSSL cannot check Ed25519 signatures here. Using the HTTPS download and SHA-256 digest only.\n' >&2 ;;
*) fail "The release manifest signature is invalid. Nothing was installed." ;;
esac
[ "$(sed -n 1p "$work/skilld-release.txt")" = "skilld-release-v1" ] || fail "The release manifest is invalid."
version=$(sed -n 2p "$work/skilld-release.txt" | sed -n 's/^version \([0-9A-Za-z.-]*\)$/\1/p')
[ -n "$version" ] || fail "The release manifest has no version."
expected=$(awk -v name="$asset" '$2 == name { print $1 }' "$work/skilld-release.txt")
[ -n "$expected" ] || fail "The release has no $asset build."
download "$release/$asset" "$work/skilld"
[ "$(sha256 "$work/skilld")" = "$expected" ] || fail "The downloaded binary does not match its digest. Nothing was installed."
chmod 755 "$work/skilld"
[ "$("$work/skilld" --version)" = "skilld $version" ] || fail "The downloaded binary reports the wrong version."
mkdir -p "$install_dir"
cp "$work/skilld" "$install_dir/.skilld-install-$$"
mv -f "$install_dir/.skilld-install-$$" "$install_dir/skilld"
printf '{"channel":"standalone"}\n' >"$install_dir/skilld-install.json"
printf 'Installed skilld %s to %s/skilld.\n' "$version" "$install_dir"
case ":$PATH:" in
*":$install_dir:"*) exit 0 ;;
esac
# The profile a new terminal reads for the shell in $SHELL, and the line that
# puts the install directory on PATH there.
case "$(basename "${SHELL:-sh}")" in
zsh) profile="${ZDOTDIR:-$HOME}/.zshrc" ;;
bash) if [ "$os" = darwin ]; then profile="$HOME/.bash_profile"; else profile="$HOME/.bashrc"; fi ;;
fish) profile="${XDG_CONFIG_HOME:-$HOME/.config}/fish/conf.d/skilld.fish" ;;
*) profile="$HOME/.profile" ;;
esac
case "$profile" in
*.fish) path_line="fish_add_path \"$install_dir\"" ;;
*) path_line="export PATH=\"$install_dir:\$PATH\"" ;;
esac
if [ "${SKILLD_NO_MODIFY_PATH:-}" = 1 ]; then
printf 'Add %s to your PATH, then run skilld --version.\n' "$install_dir"
exit 0
fi
# A reinstall finds the line from the last run and adds no second one.
if [ -f "$profile" ] && grep -qF "$path_line" "$profile"; then
:
elif mkdir -p "$(dirname "$profile")" 2>/dev/null && printf '\n# skilld\n%s\n' "$path_line" >>"$profile" 2>/dev/null; then
printf 'Added %s to your PATH in %s.\n' "$install_dir" "$profile"
else
printf 'Could not write %s. Add this line to your shell profile:\n %s\n' "$profile" "$path_line"
exit 0
fi
printf 'Open a new terminal, then run skilld --version.\n'