Skip to content

Commit 603f054

Browse files
authored
Allow users to install any release via install.sh (#49)
This PR fixes several problems with the `install.sh` script: 1. The script relied on the GitHub rest API to get a list of releases. The return from the API is paginated and only returns 30 items by default. The script now has an optional `count` argument for the `-l` option that allows the user to specify how many releases should be returned. 2. More significantly, the script was using the returned list of releases to determine if a release is available. Since the list was truncated to 30 items, older releases such as the 2023.4.2 version were not seen as available. The script now checks directly with the REST API to determine if a release is available, so the pagination is no longer an issue. 3. Parsing of options with optional arguments was not being done correctly when the short version of the option was used. This is now working correctly. 4. Added a "Test" option that skips all commands that directly make changes to the system. This makes it easier to debug the script without risking making unwanted changes. 5. The script used a pretty restrictive filter for which releases to list and it wouldn't allow users to install "Dev" or "rc" releases. The filter is now much less restrictive. 6. The script now installs the correct jammy repository for Ubuntu 24.04 on x86 systems. NOTE: Raspberry Pi images include `libcamera-dev/stable 0.4.0+rpt20250127-3`. They will only work for PhotonVision jars that include libcameraDriverVersion = v2025.0.4. Documentation update: PhotonVision/photonvision#1746
1 parent 0bbdf41 commit 603f054

File tree

1 file changed

+115
-106
lines changed

1 file changed

+115
-106
lines changed

install.sh

Lines changed: 115 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

3-
# Verbose and exit on errors
4-
set -ex
3+
# Exit on errors
4+
set -e
55

66
needs_arg() {
77
if [ -z "$OPTARG" ]; then
@@ -20,7 +20,7 @@ die() {
2020
debug() {
2121
if [ -z "$QUIET" ] ; then
2222
for arg in "$@"; do
23-
echo "$arg"
23+
echo "$TEST$arg"
2424
done
2525
fi
2626
}
@@ -34,61 +34,32 @@ install_if_missing() {
3434
debug "Found existing $1. Skipping..."
3535
# Always mark our upstream apt deps as held back, which will prevent the package
3636
# from being automatically installed, upgraded or removed
37-
apt-mark manual "$1"
37+
if [[ -z $TEST ]]; then
38+
apt-mark manual "$1"
39+
fi
3840
return
3941
fi
4042

4143
debug "Installing $1..."
42-
apt-get install --yes "$1"
43-
# Always mark our upstream apt deps as held back, which will prevent the package
44-
# from being automatically installed, upgraded or removed
45-
apt-mark manual "$1"
46-
debug "$1 installation complete."
47-
}
48-
49-
get_photonvision_releases() {
50-
# Return cached input
51-
if [ -n "$PHOTON_VISION_RELEASES" ] ; then
52-
echo "$PHOTON_VISION_RELEASES"
53-
return
54-
fi
55-
56-
# Use curl if available, otherwise fallback to wget
57-
if command -v curl > /dev/null 2>&1 ; then
58-
PHOTON_VISION_RELEASES="$(curl -sk https://api.github.com/repos/photonvision/photonvision/releases)"
59-
else
60-
PHOTON_VISION_RELEASES="$(wget -qO- https://api.github.com/repos/photonvision/photonvision/releases)"
44+
if [[ -z $TEST ]]; then
45+
apt-get install --yes "$1"
46+
# Always mark our upstream apt deps as held back, which will prevent the package
47+
# from being automatically installed, upgraded or removed
48+
apt-mark manual "$1"
6149
fi
62-
63-
echo "$PHOTON_VISION_RELEASES"
50+
debug "$1 installation complete."
6451
}
6552

6653
get_versions() {
67-
if [ -z "$PHOTON_VISION_VERSIONS" ] ; then
68-
PHOTON_VISION_VERSIONS=$(get_photonvision_releases | \
69-
sed -En 's/\"tag_name\": \"v([0-9]+\.[0-9]+\.[0-9]+)(-(beta|alpha)(-[0-9])?(\.[0-9]+)?)?\",/\1\2/p' | \
70-
sed 's/^[[:space:]]*//')
71-
fi
54+
PHOTON_VISION_RELEASES="$(wget -qO- https://api.github.com/repos/photonvision/photonvision/releases?per_page=$1)"
7255

56+
PHOTON_VISION_VERSIONS=$(get_photonvision_releases | \
57+
sed -En 's/\"tag_name\": \"(.+)\",/\1/p' | \
58+
sed 's/^[[:space:]]*//'
59+
)
7360
echo "$PHOTON_VISION_VERSIONS"
7461
}
7562

76-
is_version_available() {
77-
local target_version="$1"
78-
79-
# latest is a special case
80-
if [ "$target_version" = "latest" ]; then
81-
return 0
82-
fi
83-
84-
# Check if multiple lines are match. You can only match 1.
85-
if [ "$(get_versions | grep -cFx "$target_version")" -ne 1 ] ; then
86-
return 1
87-
fi
88-
89-
return 0
90-
}
91-
9263
is_chroot() {
9364
if systemd-detect-virt -r; then
9465
return 0
@@ -106,12 +77,13 @@ Syntax: sudo ./install.sh [options]
10677
options:
10778
-h, --help
10879
Display this help message.
109-
-l, --list-versions
110-
Lists all available versions of PhotonVision.
80+
-l [count], --list-versions=[count]
81+
Lists the most recent versions of PhotonVision.
82+
Count: Number of recent versions to show, max value is 100.
83+
Default: 30
11184
-v <version>, --version=<version>
11285
Specifies which version of PhotonVision to install.
11386
If not specified, the latest stable release is installed.
114-
Ignores leading 'v's.
11587
-a <arch>, --arch=<arch>
11688
Install PhotonVision for the specified architecture.
11789
Supported values: aarch64, x86_64
@@ -126,18 +98,27 @@ Syntax: sudo ./install.sh [options]
12698
-q, --quiet
12799
Silent install, automatically accepts all defaults. For
128100
non-interactive use. Makes -m,--install-nm default to "no".
101+
-t, --test
102+
Run in test mode. All actions that make chnages to the system
103+
are suppressed.
129104
130105
EOF
131106
}
132107

133108
INSTALL_NETWORK_MANAGER="ask"
134109
VERSION="latest"
135110

136-
while getopts "hlv:a:mnq-:" OPT; do
111+
while getopts "hlv:a:mnqt-:" OPT; do
137112
if [ "$OPT" = "-" ]; then
138113
OPT="${OPTARG%%=*}" # extract long option name
139114
OPTARG="${OPTARG#"$OPT"}" # extract long option argument (may be empty)
140115
OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=`
116+
else
117+
nextopt=${!OPTIND} # check for an optional argument followinng a short option
118+
if [[ -n $nextopt && $nextopt != -* ]]; then
119+
OPTIND=$((OPTIND + 1))
120+
OPTARG=$nextopt
121+
fi
141122
fi
142123

143124
case "$OPT" in
@@ -146,17 +127,18 @@ while getopts "hlv:a:mnq-:" OPT; do
146127
exit 0
147128
;;
148129
l | list-versions)
149-
get_versions
130+
COUNT=${OPTARG:-30}
131+
get_versions "$COUNT"
150132
exit 0
151133
;;
152134
v | version)
153135
needs_arg
154-
VERSION=${OPTARG#v} # drop leading 'v's
136+
VERSION=${OPTARG}
155137
;;
156138
a | arch) needs_arg; ARCH=$OPTARG
157139
;;
158140
m | install-nm)
159-
INSTALL_NETWORK_MANAGER="$(echo "${OPTARG:-'yes'}" | tr '[:upper:]' '[:lower:]')"
141+
INSTALL_NETWORK_MANAGER="$(echo "${OPTARG:-yes}" | tr '[:upper:]' '[:lower:]')"
160142
case "$INSTALL_NETWORK_MANAGER" in
161143
yes)
162144
;;
@@ -173,6 +155,8 @@ while getopts "hlv:a:mnq-:" OPT; do
173155
;;
174156
q | quiet) QUIET="true"
175157
;;
158+
t | test) TEST="[TEST]:"
159+
;;
176160
\?) # Handle invalid short options
177161
die "Error: Invalid option -$OPTARG" \
178162
"See './install.sh -h' for more information."
@@ -184,7 +168,9 @@ while getopts "hlv:a:mnq-:" OPT; do
184168
esac
185169
done
186170

187-
if [ "$(id -u)" != "0" ]; then
171+
debug "This is the installation script for PhotonVision."
172+
173+
if [[ "$(id -u)" != "0" && -z $TEST ]]; then
188174
die "This script must be run as root"
189175
fi
190176

@@ -211,9 +197,26 @@ else
211197
"Run './install.sh -h' for more information."
212198
fi
213199

214-
debug "This is the installation script for PhotonVision."
215200
debug "Installing for platform $ARCH"
216201

202+
# make sure that we are downloading a valid version
203+
if [ "$VERSION" = "latest" ] ; then
204+
RELEASE_URL="https://api.github.com/repos/photonvision/photonvision/releases/latest"
205+
else
206+
RELEASE_URL="https://api.github.com/repos/photonvision/photonvision/releases/tags/$VERSION"
207+
fi
208+
209+
DOWNLOAD_URL=$(curl -sk "$RELEASE_URL" |
210+
grep "browser_download_url.*$ARCH_NAME.jar" |
211+
cut -d : -f 2,3 |
212+
tr -d '"'
213+
)
214+
215+
if [[ -z $DOWNLOAD_URL ]] ; then
216+
die "PhotonVision '$VERSION' is not available for $ARCH_NAME!" \
217+
"See ./install --list-versions for a list of available versions."
218+
fi
219+
217220
DISTRO=$(lsb_release -is)
218221

219222
# Only ask if it makes sense to do so.
@@ -236,7 +239,9 @@ if [[ "$INSTALL_NETWORK_MANAGER" == "ask" ]]; then
236239
fi
237240

238241
debug "Updating package list..."
239-
apt-get update
242+
if [[ -z $TEST ]]; then
243+
apt-get update
244+
fi
240245
debug "Updated package list."
241246

242247
install_if_missing curl
@@ -248,33 +253,43 @@ install_if_missing sqlite3
248253
install_if_missing openjdk-17-jre-headless
249254

250255
debug "Setting cpufrequtils to performance mode"
251-
if [ -f /etc/default/cpufrequtils ]; then
252-
sed -i -e 's/^#\?GOVERNOR=.*$/GOVERNOR=performance/' /etc/default/cpufrequtils
253-
else
254-
echo 'GOVERNOR=performance' > /etc/default/cpufrequtils
256+
if [[ -z $TEST ]]; then
257+
if [ -f /etc/default/cpufrequtils ]; then
258+
sed -i -e 's/^#\?GOVERNOR=.*$/GOVERNOR=performance/' /etc/default/cpufrequtils
259+
else
260+
echo 'GOVERNOR=performance' > /etc/default/cpufrequtils
261+
fi
255262
fi
256263

257264
if [[ "$INSTALL_NETWORK_MANAGER" == "yes" ]]; then
258-
debug "NetworkManager installation specified. Installing components..."
265+
debug "NetworkManager installation requested. Installing components..."
259266
install_if_missing network-manager
260267
install_if_missing net-tools
261268

262269
debug "Configuring..."
263-
systemctl disable systemd-networkd-wait-online.service
264-
if [[ -d /etc/netplan/ ]]; then
265-
cat > /etc/netplan/00-default-nm-renderer.yaml <<EOF
270+
if [[ -z $TEST ]]; then
271+
systemctl disable systemd-networkd-wait-online.service
272+
if [[ -d /etc/netplan/ ]]; then
273+
cat > /etc/netplan/00-default-nm-renderer.yaml <<EOF
266274
network:
267275
renderer: NetworkManager
268276
EOF
277+
fi
278+
debug "network-manager installation complete."
269279
fi
270-
debug "network-manager installation complete."
271280
fi
272281

273282
debug ""
274283
debug "Installing additional math packages"
275284
if [[ "$DISTRO" = "Ubuntu" && -z $(apt-cache search libcholmod3) ]]; then
276285
debug "Adding jammy to list of apt sources"
277-
add-apt-repository -y -S 'deb http://ports.ubuntu.com/ubuntu-ports jammy main universe'
286+
if [[ -z $TEST ]]; then
287+
if [[ "$ARCH" = "x86_64" ]]; then
288+
add-apt-repository -y -S 'deb http://security.ubuntu.com/ubuntu jammy main universe'
289+
else
290+
add-apt-repository -y -S 'deb http://ports.ubuntu.com/ubuntu-ports jammy main universe'
291+
fi
292+
fi
278293
fi
279294

280295
install_if_missing libcholmod3
@@ -283,42 +298,35 @@ install_if_missing libsuitesparseconfig5
283298

284299
debug ""
285300

286-
if ! is_version_available "$VERSION" ; then
287-
die "PhotonVision v$VERSION is not available" \
288-
"See ./install --list-versions for a complete list of available versions."
289-
fi
301+
debug "Downloading PhotonVision '$VERSION'..."
290302

291-
if [ "$VERSION" = "latest" ] ; then
292-
RELEASE_URL="https://api.github.com/repos/photonvision/photonvision/releases/latest"
293-
debug "Downloading PhotonVision (latest)..."
294-
else
295-
RELEASE_URL="https://api.github.com/repos/photonvision/photonvision/releases/tags/v$VERSION"
296-
debug "Downloading PhotonVision (v$VERSION)..."
303+
if [[ -z $TEST ]]; then
304+
mkdir -p /opt/photonvision
305+
cd /opt/photonvision || die "Tried to enter /opt/photonvision, but it was not created."
306+
curl -sk "$RELEASE_URL" |
307+
grep "browser_download_url.*$ARCH_NAME.jar" |
308+
cut -d : -f 2,3 |
309+
tr -d '"' |
310+
wget -qi - -O photonvision.jar
297311
fi
298-
299-
mkdir -p /opt/photonvision
300-
cd /opt/photonvision || die "Tried to enter /opt/photonvision, but it was not created."
301-
curl -sk "$RELEASE_URL" |
302-
grep "browser_download_url.*$ARCH_NAME.jar" |
303-
cut -d : -f 2,3 |
304-
tr -d '"' |
305-
wget -qi - -O photonvision.jar
306312
debug "Downloaded PhotonVision."
307313

308314
debug "Creating the PhotonVision systemd service..."
309315

310-
# service --status-all doesn't list photonvision on OrangePi use systemctl instead:
311-
if [[ $(systemctl --quiet is-active photonvision) = "active" ]]; then
312-
debug "PhotonVision is already running. Stopping service."
313-
systemctl stop photonvision
314-
systemctl disable photonvision
315-
rm /lib/systemd/system/photonvision.service
316-
rm /etc/systemd/system/photonvision.service
317-
systemctl daemon-reload
318-
systemctl reset-failed
319-
fi
320316

321-
cat > /lib/systemd/system/photonvision.service <<EOF
317+
if [[ -z $TEST ]]; then
318+
# service --status-all doesn't list photonvision on OrangePi use systemctl instead:
319+
if [[ $(systemctl --quiet is-active photonvision) = "active" ]]; then
320+
debug "PhotonVision is already running. Stopping service."
321+
systemctl stop photonvision
322+
systemctl disable photonvision
323+
rm /lib/systemd/system/photonvision.service
324+
rm /etc/systemd/system/photonvision.service
325+
systemctl daemon-reload
326+
systemctl reset-failed
327+
fi
328+
329+
cat > /lib/systemd/system/photonvision.service <<EOF
322330
[Unit]
323331
Description=Service that runs PhotonVision
324332
@@ -340,19 +348,20 @@ RestartSec=1
340348
WantedBy=multi-user.target
341349
EOF
342350

343-
if [ "$DISABLE_NETWORKING" = "true" ]; then
344-
sed -i "s/photonvision.jar/photonvision.jar -n/" /lib/systemd/system/photonvision.service
345-
fi
351+
if [ "$DISABLE_NETWORKING" = "true" ]; then
352+
sed -i "s/photonvision.jar/photonvision.jar -n/" /lib/systemd/system/photonvision.service
353+
fi
346354

347-
if grep -q "RK3588" /proc/cpuinfo; then
348-
debug "This has a Rockchip RK3588, enabling big cores"
349-
sed -i 's/# AllowedCPUs=4-7/AllowedCPUs=4-7/g' /lib/systemd/system/photonvision.service
350-
fi
355+
if grep -q "RK3588" /proc/cpuinfo; then
356+
debug "This has a Rockchip RK3588, enabling big cores"
357+
sed -i 's/# AllowedCPUs=4-7/AllowedCPUs=4-7/g' /lib/systemd/system/photonvision.service
358+
fi
351359

352-
cp /lib/systemd/system/photonvision.service /etc/systemd/system/photonvision.service
353-
chmod 644 /etc/systemd/system/photonvision.service
354-
systemctl daemon-reload
355-
systemctl enable photonvision.service
360+
cp /lib/systemd/system/photonvision.service /etc/systemd/system/photonvision.service
361+
chmod 644 /etc/systemd/system/photonvision.service
362+
systemctl daemon-reload
363+
systemctl enable photonvision.service
364+
fi
356365

357366
debug "Created PhotonVision systemd service."
358367

0 commit comments

Comments
 (0)