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
|
#!/usr/bin/env bash
set -euo pipefail
# ββββββββββββββββββββββββββββββββββββββββββββββ
# ev installer
# Usage: curl -fsSL https://raw.githubusercontent.com/adrian-lorenz/ev/main/install.sh | bash
# ββββββββββββββββββββββββββββββββββββββββββββββ
REPO="adrian-lorenz/ev"
BINARY="ev"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
# ββ colours ββββββββββββββββββββββββββββββββββ
if [ -t 1 ]; then
GREEN="\033[0;32m"; YELLOW="\033[0;33m"; RED="\033[0;31m"; BOLD="\033[1m"; RESET="\033[0m"
else
GREEN=""; YELLOW=""; RED=""; BOLD=""; RESET=""
fi
info() { echo -e "${BOLD}${GREEN}β${RESET} $*"; }
warn() { echo -e "${YELLOW}!${RESET} $*"; }
fatal() { echo -e "${RED}β${RESET} $*" >&2; exit 1; }
heading() { echo -e "\n${BOLD}$*${RESET}"; }
# ββ dependency check βββββββββββββββββββββββββ
for cmd in curl tar uname; do
command -v "$cmd" >/dev/null 2>&1 || fatal "Required command not found: $cmd"
done
# ββ detect OS ββββββββββββββββββββββββββββββββ
heading "Detecting systemβ¦"
RAW_OS=$(uname -s)
case "$RAW_OS" in
Linux) GOOS="linux" ;;
Darwin) GOOS="darwin" ;;
MINGW*|MSYS*|CYGWIN*) GOOS="windows" ;;
*) fatal "Unsupported OS: $RAW_OS" ;;
esac
# ββ detect architecture βββββββββββββββββββββββ
RAW_ARCH=$(uname -m)
case "$RAW_ARCH" in
x86_64) GOARCH="amd64" ;;
aarch64|arm64) GOARCH="arm64" ;;
*) fatal "Unsupported architecture: $RAW_ARCH" ;;
esac
info "OS: $GOOS / Arch: $GOARCH"
# ββ fetch latest version ββββββββββββββββββββββ
heading "Fetching latest releaseβ¦"
VERSION=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \
| grep '"tag_name"' \
| sed 's/.*"tag_name": *"\([^"]*\)".*/\1/')
[ -z "$VERSION" ] && fatal "Could not determine latest version. Check https://github.com/${REPO}/releases"
info "Latest version: ${VERSION}"
# ββ build download URL ββββββββββββββββββββββββ
if [ "$GOOS" = "windows" ]; then
ARCHIVE="${BINARY}_${GOOS}_${GOARCH}.zip"
else
ARCHIVE="${BINARY}_${GOOS}_${GOARCH}.tar.gz"
fi
URL="https://github.com/${REPO}/releases/download/${VERSION}/${ARCHIVE}"
CHECKSUM_URL="https://github.com/${REPO}/releases/download/${VERSION}/checksums.txt"
# ββ download ββββββββββββββββββββββββββββββββββ
heading "Downloading ${ARCHIVE}β¦"
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
curl -fSL --progress-bar "$URL" -o "${TMP_DIR}/${ARCHIVE}"
curl -fsSL "$CHECKSUM_URL" -o "${TMP_DIR}/checksums.txt"
info "Downloaded successfully"
# ββ verify checksum βββββββββββββββββββββββββββ
heading "Verifying checksumβ¦"
cd "$TMP_DIR"
EXPECTED=$(grep " ${ARCHIVE}$" checksums.txt | awk '{print $1}')
[ -z "$EXPECTED" ] && fatal "Could not find checksum for ${ARCHIVE} in checksums.txt"
if command -v shasum >/dev/null 2>&1; then
ACTUAL=$(shasum -a 256 "$ARCHIVE" | awk '{print $1}')
elif command -v sha256sum >/dev/null 2>&1; then
ACTUAL=$(sha256sum "$ARCHIVE" | awk '{print $1}')
else
warn "No sha256sum or shasum found β skipping checksum verification"
ACTUAL="$EXPECTED"
fi
[ "$EXPECTED" = "$ACTUAL" ] \
|| fatal "Checksum verification failed β the download may be corrupted or tampered with"
info "Checksum OK"
# ββ extract βββββββββββββββββββββββββββββββββββ
heading "Extractingβ¦"
if [ "$GOOS" = "windows" ]; then
unzip -q "${ARCHIVE}" "${BINARY}.exe"
BINARY="${BINARY}.exe"
else
tar -xzf "${ARCHIVE}" "$BINARY"
fi
chmod +x "$BINARY"
# ββ install βββββββββββββββββββββββββββββββββββ
heading "Installing to ${INSTALL_DIR}β¦"
if [ -w "$INSTALL_DIR" ]; then
mv "$BINARY" "${INSTALL_DIR}/${BINARY}"
else
warn "Need sudo to write to ${INSTALL_DIR}"
sudo mv "$BINARY" "${INSTALL_DIR}/${BINARY}"
fi
# ββ done ββββββββββββββββββββββββββββββββββββββ
echo ""
echo -e "${BOLD}${GREEN}ev ${VERSION} installed!${RESET}"
echo ""
echo " Location : ${INSTALL_DIR}/${BINARY}"
echo ""
echo " Get started:"
echo " ev init"
echo " ev set MY_SECRET"
echo " ev run <your-command>"
echo ""
echo " Web UI:"
echo " ev manage"
echo ""
|