Skip to content

Commit 2c363f9

Browse files
committed
feat(ci+runner): versioned builds, sane status JSON, safe dry-runs, and policy-aware previews
1 parent c113cd3 commit 2c363f9

File tree

11 files changed

+174
-62
lines changed

11 files changed

+174
-62
lines changed

.github/workflows/static.yml

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,19 @@ jobs:
5050
test -f Scripts/update/apply.sh
5151
test -f Scripts/update/status.sh
5252
# Determine version from serverutils (robust)
53-
ver=$(awk -F '"' '/^VERSION=/ {print $2; exit}' serverutils)
54-
if [ -z "${ver:-}" ]; then echo "VERSION not found in serverutils" >&2; exit 1; fi
53+
base_ver=$(awk -F '"' '/^VERSION=/ {print $2; exit}' serverutils)
54+
if [ -z "${base_ver:-}" ]; then echo "VERSION not found in serverutils" >&2; exit 1; fi
55+
build_date=$(date -u +"%F")
56+
short_sha=$(git rev-parse --short HEAD)
57+
full_ver="${base_ver}+${build_date}.g${short_sha}"
58+
echo "Computed full version: $full_ver"
59+
# Stage build with VERSION baked in
60+
rm -rf build && mkdir -p build
61+
cp -a serverutils Scripts asset systemd config asciiart.ascii build/
62+
sed -i "s/^VERSION=\".*\"/VERSION=\"${full_ver}\"/" build/serverutils
5563
# Build versioned tarball with runner + scripts and assets
56-
ver_tar="site/releases/solen-${ver}.tar.gz"
57-
tar -czf "$ver_tar" serverutils Scripts asset systemd config asciiart.ascii
64+
ver_tar="site/releases/solen-${full_ver}.tar.gz"
65+
tar -czf "$ver_tar" -C build .
5866
# Verify tarball contains required libs (avoid SIGPIPE under pipefail)
5967
tmp_tar_list=$(mktemp)
6068
tar -tf "$ver_tar" > "$tmp_tar_list"
@@ -69,16 +77,19 @@ jobs:
6977
cp -f "$ver_tar" site/releases/solen-nightly.tar.gz
7078
cp -f "$ver_tar" site/releases/solen-latest.tar.gz
7179
# Checksums for each published filename
72-
(cd site/releases && sha256sum "solen-${ver}.tar.gz" > "solen-${ver}.tar.gz.sha256")
80+
(cd site/releases && sha256sum "solen-${full_ver}.tar.gz" > "solen-${full_ver}.tar.gz.sha256")
7381
(cd site/releases && sha256sum solen-stable.tar.gz > solen-stable.tar.gz.sha256)
7482
(cd site/releases && sha256sum solen-rc.tar.gz > solen-rc.tar.gz.sha256)
7583
(cd site/releases && sha256sum solen-nightly.tar.gz > solen-nightly.tar.gz.sha256)
7684
(cd site/releases && sha256sum solen-latest.tar.gz > solen-latest.tar.gz.sha256)
7785
- name: Build channel manifests
7886
run: |
7987
set -euo pipefail
80-
ver=$(awk -F '"' '/^VERSION=/ {print $2; exit}' serverutils)
81-
test -n "$ver"
88+
base_ver=$(awk -F '"' '/^VERSION=/ {print $2; exit}' serverutils)
89+
test -n "$base_ver"
90+
build_date=$(date -u +"%F")
91+
short_sha=$(git rev-parse --short HEAD)
92+
ver="${base_ver}+${build_date}.g${short_sha}"
8293
sha_stable=$(awk '{print $1}' site/releases/solen-stable.tar.gz.sha256)
8394
sha_rc=$(awk '{print $1}' site/releases/solen-rc.tar.gz.sha256)
8495
sha_nightly=$(awk '{print $1}' site/releases/solen-nightly.tar.gz.sha256)

Scripts/backups/run.sh

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,22 @@ ret_days="${ret_days:-7}"
106106

107107
# Policy tokens (scaffold): backup-profile:<name>, backup-path:<dest>
108108
if ! solen_policy_allows_token "backup-profile:${profile}"; then
109-
msg="policy refused: backup-profile:${profile}"
110-
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
111-
exit 4
109+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 || ${SOLEN_FLAG_YES:-0} -eq 0 ]]; then
110+
policy_denied_profile=1
111+
else
112+
msg="policy refused: backup-profile:${profile}"
113+
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
114+
exit 4
115+
fi
112116
fi
113117
if ! solen_policy_allows_token "backup-path:${dest}"; then
114-
msg="policy refused: backup-path:${dest}"
115-
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
116-
exit 4
118+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 || ${SOLEN_FLAG_YES:-0} -eq 0 ]]; then
119+
policy_denied_dest=1
120+
else
121+
msg="policy refused: backup-path:${dest}"
122+
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
123+
exit 4
124+
fi
117125
fi
118126

119127
# Enforce dry-run by default (safety); require --yes for real changes
@@ -281,9 +289,17 @@ if [[ "$cmd" == "run" ]]; then
281289
rollup="would back up ${#SRC_PATHS[@]} source(s) using $([[ $use_kopia -eq 1 ]] && echo kopia || echo scaffold), would prune ${prune_planned}"
282290
echo "would change $(( ${#SRC_PATHS[@]} + prune_planned + 1 )) items"
283291
if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
284-
solen_json_record ok "$rollup" "$actions_list" "\"metrics\":{\"sources\":${#SRC_PATHS[@]},\"prune_planned\":${prune_planned}}"
292+
if [[ ${policy_denied_profile:-0} -eq 1 || ${policy_denied_dest:-0} -eq 1 ]]; then
293+
solen_json_record warn "policy would refuse backup (dry-run)" "$actions_list" "\"metrics\":{\"sources\":${#SRC_PATHS[@]},\"prune_planned\":${prune_planned}}"
294+
else
295+
solen_json_record ok "$rollup" "$actions_list" "\"metrics\":{\"sources\":${#SRC_PATHS[@]},\"prune_planned\":${prune_planned}}"
296+
fi
285297
else
286-
solen_ok "$rollup"
298+
if [[ ${policy_denied_profile:-0} -eq 1 || ${policy_denied_dest:-0} -eq 1 ]]; then
299+
solen_warn "policy would refuse backup (dry-run)"
300+
else
301+
solen_ok "$rollup"
302+
fi
287303
fi
288304
exit 0
289305
else

Scripts/docker/update-docker-compose-app.sh

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,16 @@ fi
8787

8888
# Policy: service restart requires allow for 'docker'
8989
if ! solen_policy_allows_service_restart "docker"; then
90-
local_msg="policy denies restarting docker services"
91-
solen_warn "$local_msg"
92-
if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
93-
solen_json_record error "$local_msg" "docker-compose pull\ndocker-compose up -d" "\"code\":4"
90+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 || ${SOLEN_FLAG_YES:-0} -eq 0 ]]; then
91+
policy_denied_docker=1
92+
else
93+
local_msg="policy denies restarting docker services"
94+
solen_warn "$local_msg"
95+
if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
96+
solen_json_record error "$local_msg" "docker-compose pull\ndocker-compose up -d" "\"code\":4"
97+
fi
98+
exit 4
9499
fi
95-
exit 4
96100
fi
97101

98102
# Build actions list
@@ -105,11 +109,19 @@ ACTIONS
105109
)
106110

107111
if [[ $SOLEN_FLAG_DRYRUN -eq 1 ]]; then
108-
solen_info "dry-run: would execute"
112+
if [[ ${policy_denied_docker:-0} -eq 1 ]]; then
113+
solen_warn "policy would refuse docker restart (dry-run)"
114+
else
115+
solen_info "[dry-run] Would execute:"
116+
fi
109117
printf '%s\n' "$actions"
110118
echo "would change 2 items"
111119
if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
112-
solen_json_record ok "would update compose app at $TARGET_DIR" "$actions" "\"would_change\":2"
120+
if [[ ${policy_denied_docker:-0} -eq 1 ]]; then
121+
solen_json_record warn "policy would refuse docker restart (dry-run)" "$actions" "\"would_change\":0"
122+
else
123+
solen_json_record ok "would update compose app at $TARGET_DIR" "$actions" "\"would_change\":2"
124+
fi
113125
fi
114126
exit 0
115127
fi

Scripts/health/check.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,5 @@ if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
153153
else
154154
case "$st" in ok) solen_ok "$summary" ;; warn) solen_warn "$summary" ;; *) solen_err "$summary" ;; esac
155155
fi
156-
exit $([[ "$st" = "ok" ]] && echo 0 || ([[ "$st" = "warn" ]] && echo 0 || echo 1))
156+
# Always exit 0 for normal/warn results so the unit appends reliably
157+
exit 0

Scripts/log-management/clear-logs.sh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,15 @@ if [ ${#TRUNCATE_LOGS[@]} -gt 0 ]; then
115115
if [ -f "$log_file" ]; then
116116
# Policy check per file
117117
if ! solen_policy_allows_prune_path "$log_file"; then
118-
solen_warn "policy denies truncating: $log_file"
119-
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "policy denies truncating $log_file" "truncate -s 0 $log_file" "\"code\":4"
120-
exit 4
118+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 || ${SOLEN_FLAG_YES:-0} -eq 0 ]]; then
119+
solen_warn "policy would deny truncating (dry-run): $log_file"
120+
actions_list+="truncate -s 0 $log_file\n"
121+
continue
122+
else
123+
solen_warn "policy denies truncating: $log_file"
124+
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "policy denies truncating $log_file" "truncate -s 0 $log_file" "\"code\":4"
125+
exit 4
126+
fi
121127
fi
122128
actions_list+="truncate -s 0 $log_file
123129
"

Scripts/network/network-info.sh

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ if [[ -n "$gateway" ]]; then
8484
fi
8585

8686
if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
87+
any_ok=0
8788
# Interfaces
8889
while IFS= read -r line; do
8990
[[ -z "$line" ]] && continue
@@ -101,6 +102,7 @@ if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
101102
D
102103
)
103104
solen_json_record_full ok "$summary" "$details"
105+
any_ok=$((any_ok+1))
104106
done < "$ifaces_tmp"
105107

106108
# Ports (if available)
@@ -129,7 +131,12 @@ D
129131
metrics_kv="\"if_up\":${up_count},\"if_total\":${total_count},\"listening\":${ports_count},\"gateway_ok\":$([[ $gateway_ok == "true" ]] && echo true || echo false)"
130132
if [[ -n "$rtt_ms" ]]; then metrics_kv+=" ,\"rtt_ms\":${rtt_ms}"; fi
131133
solen_json_record ok "$rollup" "" "$metrics_kv"
132-
exit 0
134+
if [[ $any_ok -gt 0 ]]; then
135+
exit 0
136+
else
137+
solen_json_record error "no interfaces enumerated" "" "\"code\":2"
138+
exit 2
139+
fi
133140
else
134141
solen_head "IP Addresses"
135142
cat "$ifaces_tmp"
@@ -141,5 +148,3 @@ else
141148
fi
142149

143150
exit 0
144-
145-
exit 0

Scripts/security/firewall-apply.sh

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,15 @@ while [[ $# -gt 0 ]]; do
7979
done
8080

8181
if ! solen_policy_allows_token "firewall-apply"; then
82-
msg="policy refused: firewall-apply"
83-
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
84-
exit 4
82+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 || ${SOLEN_FLAG_YES:-0} -eq 0 ]]; then
83+
# In dry-run, warn and continue to print a plan but do not fail hard
84+
: # plan gets generated below; we will emit warn at the end if needed
85+
policy_denied_dryrun=1
86+
else
87+
msg="policy refused: firewall-apply"
88+
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
89+
exit 4
90+
fi
8591
fi
8692

8793
# Normalize allow specs into proto and port
@@ -230,10 +236,18 @@ fi
230236

231237
if [[ $SOLEN_FLAG_DRYRUN -eq 1 || $SOLEN_FLAG_YES -eq 0 ]]; then
232238
[[ $SOLEN_FLAG_JSON -eq 1 ]] && {
233-
solen_json_record ok "dry-run: $summary" "$actions" "\"would_change\":1"
239+
if [[ ${policy_denied_dryrun:-0} -eq 1 ]]; then
240+
solen_json_record warn "policy would refuse: firewall-apply (dry-run)" "$actions" "\"would_change\":0"
241+
else
242+
solen_json_record ok "dry-run: $summary" "$actions" "\"would_change\":1"
243+
fi
234244
exit 0
235245
}
236-
solen_info "dry-run enforced (use --yes to apply)"
246+
if [[ ${policy_denied_dryrun:-0} -eq 1 ]]; then
247+
solen_warn "policy would refuse: firewall-apply (dry-run)"
248+
else
249+
solen_info "dry-run enforced (use --yes to apply)"
250+
fi
237251
printf '%s' "$actions"
238252
exit 0
239253
fi

Scripts/security/ssh-harden.sh

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,13 @@ while [[ $# -gt 0 ]]; do
6969
done
7070

7171
if ! solen_policy_allows_token "ssh-config-apply"; then
72-
msg="policy refused: ssh-config-apply"
73-
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
74-
exit 4
72+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 || ${SOLEN_FLAG_YES:-0} -eq 0 ]]; then
73+
policy_denied_dryrun=1
74+
else
75+
msg="policy refused: ssh-config-apply"
76+
[[ $SOLEN_FLAG_JSON -eq 1 ]] && solen_json_record error "$msg" "" "\"code\":4" || solen_err "$msg"
77+
exit 4
78+
fi
7579
fi
7680

7781
# Rollback: restore latest backup and exit
@@ -209,9 +213,17 @@ summary="sshd hardened (root=${permit_root}, passwords=${password_auth}${port:+,
209213

210214
if [[ $SOLEN_FLAG_DRYRUN -eq 1 || $SOLEN_FLAG_YES -eq 0 ]]; then
211215
if [[ $SOLEN_FLAG_JSON -eq 1 ]]; then
212-
solen_json_record ok "dry-run: $summary" "$actions" "\"would_change\":1"
216+
if [[ ${policy_denied_dryrun:-0} -eq 1 ]]; then
217+
solen_json_record warn "policy would refuse: ssh-config-apply (dry-run)" "$actions" "\"would_change\":0"
218+
else
219+
solen_json_record ok "dry-run: $summary" "$actions" "\"would_change\":1"
220+
fi
213221
else
214-
solen_info "dry-run enforced (use --yes to apply)"
222+
if [[ ${policy_denied_dryrun:-0} -eq 1 ]]; then
223+
solen_warn "policy would refuse: ssh-config-apply (dry-run)"
224+
else
225+
solen_info "dry-run enforced (use --yes to apply)"
226+
fi
215227
printf '%s' "$actions"
216228
fi
217229
rm -f "$tmp" || true

Scripts/system-maintenance/cleanup-system.sh

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@
1414
# Strict mode
1515
set -euo pipefail
1616

17+
THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18+
if [ -f "${THIS_DIR}/../lib/solen.sh" ]; then . "${THIS_DIR}/../lib/solen.sh"; fi
19+
type solen_init_flags >/dev/null 2>&1 || solen_init_flags() { : "${SOLEN_FLAG_YES:=0}"; : "${SOLEN_FLAG_JSON:=0}"; : "${SOLEN_FLAG_DRYRUN:=1}"; [ "$SOLEN_FLAG_YES" = 1 ] && SOLEN_FLAG_DRYRUN=0 || true; }
20+
type solen_parse_common_flag >/dev/null 2>&1 || solen_parse_common_flag() { case "$1" in --yes|-y) SOLEN_FLAG_YES=1; SOLEN_FLAG_DRYRUN=0; return 0;; --dry-run) SOLEN_FLAG_DRYRUN=1; return 0;; --json) SOLEN_FLAG_JSON=1; return 0;; esac; return 1; }
21+
type solen_info >/dev/null 2>&1 || solen_info(){ echo -e "\033[0;36mℹ️ $*\033[0m"; }
22+
type solen_ok >/dev/null 2>&1 || solen_ok(){ echo -e "\033[0;32m✅ $*\033[0m"; }
23+
type solen_warn >/dev/null 2>&1 || solen_warn(){ echo -e "\033[0;33m⚠️ $*\033[0m"; }
24+
type solen_json_record >/dev/null 2>&1 || solen_json_record(){ printf '{"status":"%s","summary":"%s","ts":"%s","host":"%s","actions":%s%s}\n' "$1" "$2" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$(hostname 2>/dev/null || uname -n)" "[]" ""; }
25+
26+
solen_init_flags
27+
28+
while [[ $# -gt 0 ]]; do
29+
if solen_parse_common_flag "$1"; then shift; continue; else break; fi
30+
done
31+
1732
# --- Configuration ---
1833
# Add any needed configuration variables here
1934

@@ -36,17 +51,27 @@ echowarn() {
3651
echo -e "${COLOR_YELLOW}⚠️ $1${COLOR_RESET}"
3752
}
3853

39-
# --- Sanity Checks ---
54+
# --- Sanity / Dry-run planning ---
55+
command -v apt > /dev/null 2>&1 || { echo >&2 "Error: apt command not found. This script requires a Debian-based system."; exit 1; }
56+
57+
actions=$'apt clean\napt autoclean -y\napt autoremove -y\n'
58+
if [[ ${SOLEN_FLAG_DRYRUN:-0} -eq 1 ]]; then
59+
solen_info "[dry-run] Would execute:"
60+
printf '%s\n' "$actions"
61+
echo "would change 3 items"
62+
if [[ ${SOLEN_FLAG_JSON:-0} -eq 1 ]]; then
63+
printf '%s\n' "$actions" | sed '/^$/d' >"/tmp/._su_actions.$$" || true
64+
solen_json_record ok "would clean apt caches and unused packages" "$(cat /tmp/._su_actions.$$ 2>/dev/null || true)" "\"would_change\":3"
65+
rm -f "/tmp/._su_actions.$$" || true
66+
fi
67+
exit 0
68+
fi
69+
4070
if [[ $EUID -ne 0 ]]; then
4171
echowarn "This script needs to be run as root (use sudo)."
4272
exit 1
4373
fi
4474

45-
command -v apt > /dev/null 2>&1 || {
46-
echo >&2 "Error: apt command not found. This script requires a Debian-based system."
47-
exit 1
48-
}
49-
5075
# --- Main Logic ---
5176
echoinfo "🧹 Starting system cleanup..."
5277

Scripts/update/check.sh

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,40 @@ CACHEFILE="${CACHEDIR}/update-cache.json"
3939

4040
tmp="$(mktemp)"
4141
checked_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
42+
host="$(hostname 2>/dev/null || uname -n)"
4243
if ! curl -fsSL --max-time 4 "$MAN_URL" -o "$tmp"; then
4344
[[ $QUIET -eq 1 ]] || echo "No update info (network)" >&2
44-
printf '{"version":"","channel":"%s","checked_at":"%s"}\n' "$CHANNEL" "$checked_at" > "$CACHEFILE.tmp" || true
45+
jq -n --arg inst "" --arg latest "" --arg ch "$CHANNEL" --arg ts "$checked_at" --arg host "$host" --arg sum "no update info (network)" \
46+
'{installed_version:$inst, latest_version:$latest, channel:$ch, breaking:false, ts:$ts, host:$host, status:"warn", summary:$sum}' \
47+
> "$CACHEFILE.tmp" || true
4548
mv "$CACHEFILE.tmp" "$CACHEFILE" 2>/dev/null || true
4649
rm -f "$tmp"
50+
[[ $JSON -eq 1 ]] && cat "$CACHEFILE" || echo "cached latest ($CHANNEL): "
4751
exit 0
4852
fi
4953

5054
# Validate minimal shape
5155
if ! jq -e '.version and .url and .sha256' "$tmp" >/dev/null 2>&1; then
5256
[[ $QUIET -eq 1 ]] || echo "Invalid manifest" >&2
53-
printf '{"version":"","channel":"%s","checked_at":"%s"}\n' "$CHANNEL" "$checked_at" > "$CACHEFILE.tmp" || true
57+
jq -n --arg inst "" --arg latest "" --arg ch "$CHANNEL" --arg ts "$checked_at" --arg host "$host" --arg sum "invalid manifest" \
58+
'{installed_version:$inst, latest_version:$latest, channel:$ch, breaking:false, ts:$ts, host:$host, status:"warn", summary:$sum}' \
59+
> "$CACHEFILE.tmp" || true
5460
mv "$CACHEFILE.tmp" "$CACHEFILE" 2>/dev/null || true
55-
rm -f "$tmp"; exit 0
61+
rm -f "$tmp"; [[ $JSON -eq 1 ]] && cat "$CACHEFILE" || echo "cached latest ($CHANNEL): "
62+
exit 0
5663
fi
5764

58-
jq --arg ch "$CHANNEL" --arg ts "$checked_at" \
59-
'.channel=$ch | .checked_at=$ts' "$tmp" > "$CACHEFILE.tmp" && mv "$CACHEFILE.tmp" "$CACHEFILE"
65+
ver=$(jq -r '.version' "$tmp")
66+
brk=$(jq -r '.breaking // false' "$tmp")
67+
jq -n --arg inst "" --arg latest "$ver" --arg ch "$CHANNEL" --arg ts "$checked_at" --argjson breaking "$brk" --arg host "$host" \
68+
--arg sum "cached latest ($CHANNEL): $ver" \
69+
'{installed_version:$inst, latest_version:$latest, channel:$ch, breaking:$breaking, ts:$ts, host:$host, status:"ok", summary:$sum}' \
70+
> "$CACHEFILE.tmp" && mv "$CACHEFILE.tmp" "$CACHEFILE"
6071
rm -f "$tmp"
6172

6273
if [[ $JSON -eq 1 ]]; then
6374
cat "$CACHEFILE"
6475
else
65-
ver="$(jq -r '.version' "$CACHEFILE")"
6676
echo "cached latest ($CHANNEL): $ver"
6777
fi
6878
exit 0

0 commit comments

Comments
 (0)