Skip to content

Commit 368e279

Browse files
committed
feat(upgrade): add reinstall-openclaw, upgrade-node, skip-reboot action params
The 'upgrade' juju action previously only ran apt-get full-upgrade and scheduled a reboot. This change adds three new optional parameters to support manual recovery of a broken OpenClaw installation. reinstall-openclaw (bool, default false) Force a clean uninstall + reinstall of OpenClaw using the configured install-method and version. Removes the /usr/local/bin/openclaw symlink, purges the existing global package (npm uninstall -g / bun remove -g / source dir removal), reinstalls from scratch, recreates the symlink, and verifies the binary is functional. Fails the action explicitly if the resulting binary cannot be found. upgrade-node (bool, default false) Upgrade Node.js to the latest patch release of the configured major version (node-version config, default 24) via nvm. Runs 'nvm install 24' which fetches the latest v24.x.x if not already cached, then updates the nvm default alias. Because nvm global npm packages are stored per-node- version, upgrade-node automatically forces reinstall-openclaw=true so OpenClaw is always reinstalled into the new Node binary. No-op when install-method=bun. skip-reboot (bool, default false) Skip the 'shutdown -r +1' scheduled at the end of the action. Useful when only fixing OpenClaw or Node.js without needing a full reboot. upgrade_nodejs() Wraps 'nvm install <major>' + alias/use default. Logs the before/after node version and returns the new version string for action-set output. reinstall_openclaw() Handles npm/pnpm, bun, and source install methods. Removes the broken installation before reinstalling so corrupted state from a failed upgrade cannot interfere. # Fix broken openclaw after a failed upgrade (no reboot): juju run linebot/leader upgrade reinstall-openclaw=true skip-reboot=true # Also pull the latest Node v24 patch (e.g. v24.14.1) and reinstall: juju run linebot/leader upgrade upgrade-node=true skip-reboot=true
1 parent 2ba9918 commit 368e279

3 files changed

Lines changed: 197 additions & 15 deletions

File tree

actions.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,26 @@ upgrade:
4949
description: |
5050
Perform a system upgrade (apt-get full-upgrade) and reboot the system.
5151
If manual=false and version="" or "latest", it also upgrades OpenClaw.
52+
Use reinstall-openclaw=true to force a clean reinstall of OpenClaw (useful
53+
when the installation is broken after a failed upgrade).
54+
params:
55+
reinstall-openclaw:
56+
type: boolean
57+
default: false
58+
description: |
59+
Force a clean reinstall of OpenClaw by uninstalling and reinstalling
60+
from scratch. Useful when openclaw is broken after a failed upgrade.
61+
upgrade-node:
62+
type: boolean
63+
default: false
64+
description: |
65+
Upgrade Node.js to the latest patch of the configured major version
66+
(node-version config, default 24) via nvm. Because nvm global packages
67+
are per-node-version, OpenClaw is automatically reinstalled in the new
68+
version regardless of the reinstall-openclaw flag.
69+
skip-reboot:
70+
type: boolean
71+
default: false
72+
description: |
73+
Skip the scheduled reboot after the upgrade. Useful when only
74+
reinstalling OpenClaw without needing a full system reboot.

actions/upgrade

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,63 @@ set -e
44
CHARM_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
55
source "$CHARM_DIR/hooks/common.sh"
66

7-
log_info "Starting system upgrade..."
7+
REINSTALL_OPENCLAW="$(action-get reinstall-openclaw)"
8+
UPGRADE_NODE="$(action-get upgrade-node)"
9+
SKIP_REBOOT="$(action-get skip-reboot)"
10+
11+
log_info "Starting system upgrade (reinstall-openclaw=$REINSTALL_OPENCLAW, upgrade-node=$UPGRADE_NODE, skip-reboot=$SKIP_REBOOT)..."
812
action-set status="running apt-get update and full-upgrade"
913

1014
export DEBIAN_FRONTEND=noninteractive
1115
sudo apt-get update
1216
sudo apt-get -yq -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" full-upgrade
1317

14-
MANAGE_CONFIG="$(should_manage_config)"
15-
VERSION="$(config-get version)"
16-
17-
if [ "$MANAGE_CONFIG" = "true" ]; then
18-
if [ -z "$VERSION" ] || [ "$VERSION" = "latest" ]; then
19-
log_info "OpenClaw configuration is auto-managed and version is set to '$VERSION'. Checking for OpenClaw updates..."
20-
action-set status="checking for openclaw update"
21-
# Force the update check by removing the rate limit file
22-
rm -f /home/ubuntu/.openclaw/.last-update-check
23-
check_and_update_openclaw || true
18+
if [ "$UPGRADE_NODE" = "true" ]; then
19+
INSTALL_METHOD="$(config-get install-method)"
20+
if [ "$INSTALL_METHOD" = "bun" ]; then
21+
log_info "install-method=bun — skipping Node.js upgrade"
22+
else
23+
action-set status="upgrading node.js"
24+
NODE_VERSION="$(upgrade_nodejs)"
25+
action-set node-version="$NODE_VERSION"
26+
log_info "Node.js upgraded to $NODE_VERSION"
27+
# nvm globals are per-version, so openclaw must be reinstalled
28+
REINSTALL_OPENCLAW="true"
2429
fi
2530
fi
2631

27-
action-set status="scheduling reboot"
28-
log_info "System upgrade complete. Scheduling reboot in 1 minute."
29-
sudo shutdown -r +1 "System upgrading via juju action 'upgrade'"
32+
if [ "$REINSTALL_OPENCLAW" = "true" ]; then
33+
log_info "Reinstalling OpenClaw from scratch as requested..."
34+
action-set status="reinstalling openclaw"
35+
if reinstall_openclaw; then
36+
INSTALLED_VERSION="$(get_installed_openclaw_version)"
37+
action-set openclaw-version="$INSTALLED_VERSION"
38+
log_info "OpenClaw reinstalled successfully: $INSTALLED_VERSION"
39+
else
40+
action-fail "OpenClaw reinstall failed - check unit logs for details"
41+
exit 1
42+
fi
43+
else
44+
MANAGE_CONFIG="$(should_manage_config)"
45+
VERSION="$(config-get version)"
3046

31-
action-set result="System upgraded and reboot scheduled"
47+
if [ "$MANAGE_CONFIG" = "true" ]; then
48+
if [ -z "$VERSION" ] || [ "$VERSION" = "latest" ]; then
49+
log_info "OpenClaw configuration is auto-managed and version is set to '$VERSION'. Checking for OpenClaw updates..."
50+
action-set status="checking for openclaw update"
51+
# Force the update check by removing the rate limit file
52+
rm -f /home/ubuntu/.openclaw/.last-update-check
53+
check_and_update_openclaw || true
54+
fi
55+
fi
56+
fi
57+
58+
if [ "$SKIP_REBOOT" = "true" ]; then
59+
log_info "System upgrade complete. Skipping reboot as requested."
60+
action-set result="System upgraded (reboot skipped)"
61+
else
62+
action-set status="scheduling reboot"
63+
log_info "System upgrade complete. Scheduling reboot in 1 minute."
64+
sudo shutdown -r +1 "System upgrading via juju action 'upgrade'"
65+
action-set result="System upgraded and reboot scheduled"
66+
fi

hooks/common.sh

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,47 @@ install_nodejs() {
204204
log_info "Node.js installed via nvm: $installed_version"
205205
}
206206

207+
# Upgrade Node.js to the latest patch of the configured major version via nvm.
208+
# After upgrading, the nvm default alias is updated to the new version.
209+
# NOTE: callers are responsible for reinstalling global npm packages (e.g. openclaw)
210+
# in the new version, since nvm globals are per-node-version.
211+
upgrade_nodejs() {
212+
local node_version nvm_dir
213+
node_version="$(config-get node-version)"
214+
nvm_dir="/home/ubuntu/.nvm"
215+
216+
if [ ! -d "$nvm_dir" ]; then
217+
log_error "nvm directory not found at $nvm_dir - cannot upgrade Node.js"
218+
return 1
219+
fi
220+
221+
log_info "Upgrading Node.js to latest v${node_version}.x via nvm"
222+
223+
local before_version after_version
224+
before_version="$(sudo -u ubuntu bash -l -c "
225+
export NVM_DIR=\"$nvm_dir\"
226+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
227+
node --version 2>/dev/null || echo unknown
228+
" 2>/dev/null | tail -1)"
229+
230+
sudo -u ubuntu bash -l -c "
231+
export NVM_DIR=\"$nvm_dir\"
232+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
233+
nvm install ${node_version}
234+
nvm alias default ${node_version}
235+
nvm use default
236+
"
237+
238+
after_version="$(sudo -u ubuntu bash -l -c "
239+
export NVM_DIR=\"$nvm_dir\"
240+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
241+
node --version 2>/dev/null || echo unknown
242+
" 2>/dev/null | tail -1)"
243+
244+
log_info "Node.js upgraded: $before_version -> $after_version"
245+
echo "$after_version"
246+
}
247+
207248
# Install Bun runtime
208249
install_bun() {
209250
log_info "Installing Bun runtime"
@@ -1471,6 +1512,89 @@ get_installed_openclaw_version() {
14711512
" 2>/dev/null || true
14721513
}
14731514

1515+
# Uninstall and reinstall OpenClaw from scratch using the configured install method.
1516+
# Useful when the installation is broken after a failed upgrade.
1517+
reinstall_openclaw() {
1518+
local install_method version
1519+
install_method="$(config-get install-method)"
1520+
version="$(config-get version)"
1521+
local install_target="openclaw"
1522+
if [ -n "$version" ] && [ "$version" != "latest" ]; then
1523+
install_target="openclaw@${version}"
1524+
else
1525+
install_target="openclaw@latest"
1526+
fi
1527+
1528+
log_info "Reinstalling OpenClaw from scratch (method: $install_method, target: $install_target)"
1529+
1530+
# Remove existing symlink
1531+
rm -f /usr/local/bin/openclaw
1532+
log_info "Removed /usr/local/bin/openclaw symlink"
1533+
1534+
case "$install_method" in
1535+
npm|pnpm)
1536+
sudo -u ubuntu bash -l -c "
1537+
export NVM_DIR=\"/home/ubuntu/.nvm\"
1538+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
1539+
nvm use $(config-get node-version)
1540+
npm uninstall -g openclaw 2>/dev/null || true
1541+
npm install -g ${install_target}
1542+
"
1543+
;;
1544+
bun)
1545+
sudo -u ubuntu bash -l -c "
1546+
export BUN_INSTALL=\"/home/ubuntu/.bun\"
1547+
export PATH=\"\$BUN_INSTALL/bin:\$PATH\"
1548+
bun remove -g openclaw 2>/dev/null || true
1549+
bun install -g ${install_target}
1550+
"
1551+
;;
1552+
source)
1553+
local src_dir="/home/ubuntu/openclaw"
1554+
if [ -d "$src_dir" ]; then
1555+
log_info "Removing existing source directory"
1556+
rm -rf "$src_dir"
1557+
fi
1558+
sudo -u ubuntu bash -l -c "
1559+
export NVM_DIR=\"/home/ubuntu/.nvm\"
1560+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
1561+
nvm use $(config-get node-version)
1562+
cd /home/ubuntu && git clone https://github.com/openclaw/openclaw.git
1563+
"
1564+
if [ -n "$version" ] && [ "$version" != "latest" ]; then
1565+
sudo -u ubuntu bash -l -c "
1566+
export NVM_DIR=\"/home/ubuntu/.nvm\"
1567+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
1568+
nvm use $(config-get node-version)
1569+
cd /home/ubuntu/openclaw && git checkout ${version}
1570+
"
1571+
fi
1572+
sudo -u ubuntu bash -l -c "
1573+
export NVM_DIR=\"/home/ubuntu/.nvm\"
1574+
[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"
1575+
nvm use $(config-get node-version)
1576+
npm install -g pnpm && cd /home/ubuntu/openclaw && pnpm install && pnpm build
1577+
"
1578+
;;
1579+
*)
1580+
log_error "Unknown install method: $install_method"
1581+
return 1
1582+
;;
1583+
esac
1584+
1585+
update_openclaw_symlink
1586+
1587+
local new_version
1588+
new_version=$(get_installed_openclaw_version)
1589+
if [ -z "$new_version" ]; then
1590+
log_error "OpenClaw reinstall failed - command not found after reinstall"
1591+
return 1
1592+
fi
1593+
1594+
log_info "OpenClaw reinstalled successfully: version $new_version"
1595+
return 0
1596+
}
1597+
14741598
# Rate-limited to once per 24 h (via timestamp file) so frequent update-status
14751599
# calls don't hammer npm. Returns 0 if an update was installed, 1 otherwise.
14761600
check_and_update_openclaw() {

0 commit comments

Comments
 (0)