Skip to content

Commit c60802e

Browse files
committed
fix(clean): harden bun cache and tap formula updates
1 parent 29d6829 commit c60802e

File tree

4 files changed

+172
-7
lines changed

4 files changed

+172
-7
lines changed

lib/clean/dev.sh

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,26 @@ clean_dev_npm() {
8989
fi
9090
local bun_default_cache="$HOME/.bun/install/cache"
9191
local bun_cache_path="$bun_default_cache"
92+
local bun_cache_cleaned=false
93+
local bun_dry_run="${DRY_RUN:-false}"
9294
if command -v bun > /dev/null 2>&1 && bun --version > /dev/null 2>&1; then
93-
clean_tool_cache "bun cache" bun pm cache rm
95+
if [[ "$bun_dry_run" != "true" ]]; then
96+
if [[ -t 1 ]]; then
97+
start_section_spinner "Cleaning bun cache..."
98+
fi
99+
if run_with_timeout 10 bun pm cache rm > /dev/null 2>&1; then
100+
bun_cache_cleaned=true
101+
fi
102+
if [[ -t 1 ]]; then
103+
stop_section_spinner
104+
fi
105+
if [[ "$bun_cache_cleaned" == "true" ]]; then
106+
echo -e " ${GREEN}${ICON_SUCCESS}${NC} bun cache"
107+
fi
108+
else
109+
echo -e " ${YELLOW}${ICON_DRY_RUN}${NC} bun cache · would clean"
110+
bun_cache_cleaned=true
111+
fi
94112

95113
start_section_spinner "Checking bun cache path..."
96114
bun_cache_path=$(run_with_timeout 2 bun pm cache 2> /dev/null) || bun_cache_path=""
@@ -112,6 +130,11 @@ clean_dev_npm() {
112130
if [[ "$bun_cache_path_normalized" != "$bun_default_cache_normalized" ]]; then
113131
safe_clean "$bun_default_cache"/* "Orphaned bun cache"
114132
fi
133+
134+
# If bun pm cache rm fails, fall back to filesystem cleanup to avoid no-op.
135+
if [[ "$bun_cache_cleaned" != "true" ]]; then
136+
safe_clean "$bun_cache_path"/* "Bun cache"
137+
fi
115138
else
116139
safe_clean "$bun_default_cache"/* "Bun cache"
117140
fi

scripts/update_homebrew_tap_formula.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,43 @@ if [[ ! -f "$formula_path" ]]; then
6464
exit 1
6565
fi
6666

67+
replacement_counts="$(
68+
TAG="$tag" \
69+
SOURCE_SHA="$source_sha" \
70+
ARM_SHA="$arm_sha" \
71+
AMD_SHA="$amd_sha" \
72+
perl -0ne '
73+
my $text = $_;
74+
75+
my $source_replacements = (
76+
$text =~ s{url "https://github.com/tw93/(?:Mole|mole)/archive/refs/tags/[^"]+\.tar\.gz"\n sha256 "[^"]+"}{
77+
qq{url "https://github.com/tw93/Mole/archive/refs/tags/$ENV{TAG}.tar.gz"\n sha256 "$ENV{SOURCE_SHA}"}
78+
}se
79+
);
80+
81+
my $arm_replacements = (
82+
$text =~ s{(on_arm do\s+url ")https://github.com/tw93/(?:Mole|mole)/releases/download/[^/]+/binaries-darwin-arm64\.tar\.gz("\s+sha256 ")[^"]+(")}{
83+
qq{$1https://github.com/tw93/Mole/releases/download/$ENV{TAG}/binaries-darwin-arm64.tar.gz$2$ENV{ARM_SHA}$3}
84+
}se
85+
);
86+
87+
my $amd_replacements = (
88+
$text =~ s{(on_intel do\s+url ")https://github.com/tw93/(?:Mole|mole)/releases/download/[^/]+/binaries-darwin-amd64\.tar\.gz("\s+sha256 ")[^"]+(")}{
89+
qq{$1https://github.com/tw93/Mole/releases/download/$ENV{TAG}/binaries-darwin-amd64.tar.gz$2$ENV{AMD_SHA}$3}
90+
}se
91+
);
92+
93+
print "$source_replacements $arm_replacements $amd_replacements\n";
94+
' "$formula_path"
95+
)"
96+
97+
read -r source_replacements arm_replacements amd_replacements <<< "$replacement_counts"
98+
99+
if [[ "$source_replacements" != "1" || "$arm_replacements" != "1" || "$amd_replacements" != "1" ]]; then
100+
echo "Failed to update formula: expected 1 replacement for source/arm/amd, got ${source_replacements}/${arm_replacements}/${amd_replacements}" >&2
101+
exit 1
102+
fi
103+
67104
TAG="$tag" \
68105
SOURCE_SHA="$source_sha" \
69106
ARM_SHA="$arm_sha" \

tests/clean_dev_caches.bats

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ source "$PROJECT_ROOT/lib/core/common.sh"
189189
source "$PROJECT_ROOT/lib/clean/dev.sh"
190190
start_section_spinner() { :; }
191191
stop_section_spinner() { :; }
192-
clean_tool_cache() { echo "$1|$*"; }
192+
clean_tool_cache() { :; }
193193
safe_clean() { echo "$2|$1"; }
194194
note_activity() { :; }
195195
run_with_timeout() { shift; "$@"; }
@@ -213,7 +213,8 @@ clean_dev_npm
213213
EOF
214214

215215
[ "$status" -eq 0 ]
216-
[[ "$output" == *"bun cache|bun cache bun pm cache rm"* ]]
216+
[[ "$output" == *"bun cache"* ]]
217+
[[ "$output" != *"Bun cache|$HOME/.bun/install/cache/*"* ]]
217218
[[ "$output" != *"Orphaned bun cache"* ]]
218219
}
219220

@@ -224,7 +225,7 @@ source "$PROJECT_ROOT/lib/core/common.sh"
224225
source "$PROJECT_ROOT/lib/clean/dev.sh"
225226
start_section_spinner() { :; }
226227
stop_section_spinner() { :; }
227-
clean_tool_cache() { echo "$1|$*"; }
228+
clean_tool_cache() { :; }
228229
safe_clean() { echo "$2|$1"; }
229230
note_activity() { :; }
230231
run_with_timeout() { shift; "$@"; }
@@ -248,7 +249,7 @@ clean_dev_npm
248249
EOF
249250

250251
[ "$status" -eq 0 ]
251-
[[ "$output" == *"bun cache|bun cache bun pm cache rm"* ]]
252+
[[ "$output" == *"bun cache"* ]]
252253
[[ "$output" == *"Orphaned bun cache|$HOME/.bun/install/cache/*"* ]]
253254
}
254255

@@ -259,7 +260,7 @@ source "$PROJECT_ROOT/lib/core/common.sh"
259260
source "$PROJECT_ROOT/lib/clean/dev.sh"
260261
start_section_spinner() { :; }
261262
stop_section_spinner() { :; }
262-
clean_tool_cache() { echo "$1|$*"; }
263+
clean_tool_cache() { :; }
263264
safe_clean() { echo "$2|$1"; }
264265
note_activity() { :; }
265266
run_with_timeout() { shift; "$@"; }
@@ -283,10 +284,45 @@ clean_dev_npm
283284
EOF
284285

285286
[ "$status" -eq 0 ]
286-
[[ "$output" == *"bun cache|bun cache bun pm cache rm"* ]]
287+
[[ "$output" == *"bun cache"* ]]
287288
[[ "$output" != *"Orphaned bun cache"* ]]
288289
}
289290

291+
@test "clean_dev_npm falls back to filesystem cleanup when bun cache command fails" {
292+
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
293+
set -euo pipefail
294+
source "$PROJECT_ROOT/lib/core/common.sh"
295+
source "$PROJECT_ROOT/lib/clean/dev.sh"
296+
start_section_spinner() { :; }
297+
stop_section_spinner() { :; }
298+
clean_tool_cache() { :; }
299+
safe_clean() { echo "$2|$1"; }
300+
note_activity() { :; }
301+
run_with_timeout() { shift; "$@"; }
302+
npm() { return 0; }
303+
bun() {
304+
if [[ "$1" == "--version" ]]; then
305+
echo "1.2.0"
306+
return 0
307+
fi
308+
if [[ "$1" == "pm" && "$2" == "cache" && "${3:-}" == "rm" ]]; then
309+
return 1
310+
fi
311+
if [[ "$1" == "pm" && "$2" == "cache" ]]; then
312+
echo "/tmp/mole-bun-cache"
313+
return 0
314+
fi
315+
return 0
316+
}
317+
export -f npm bun
318+
clean_dev_npm
319+
EOF
320+
321+
[ "$status" -eq 0 ]
322+
[[ "$output" == *"Bun cache|/tmp/mole-bun-cache/*"* ]]
323+
[[ "$output" == *"Orphaned bun cache|$HOME/.bun/install/cache/*"* ]]
324+
}
325+
290326
@test "clean_dev_docker skips daemon-managed cleanup by default" {
291327
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=false bash --noprofile --norc <<'EOF'
292328
set -euo pipefail

tests/scripts.bats

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,72 @@ EOF
131131
run bash -c "grep -q 'MOLE_VERSION=\"dev\"' '$PROJECT_ROOT/install.sh'"
132132
[ "$status" -eq 0 ]
133133
}
134+
135+
@test "update_homebrew_tap_formula.sh updates all release artifacts" {
136+
local formula_file="$HOME/mole.rb"
137+
cat > "$formula_file" <<'EOF'
138+
class Mole < Formula
139+
desc "Mole"
140+
homepage "https://github.com/tw93/Mole"
141+
url "https://github.com/tw93/Mole/archive/refs/tags/V1.32.0.tar.gz"
142+
sha256 "old-source-sha"
143+
144+
on_arm do
145+
url "https://github.com/tw93/Mole/releases/download/V1.32.0/binaries-darwin-arm64.tar.gz"
146+
sha256 "old-arm-sha"
147+
end
148+
149+
on_intel do
150+
url "https://github.com/tw93/Mole/releases/download/V1.32.0/binaries-darwin-amd64.tar.gz"
151+
sha256 "old-amd-sha"
152+
end
153+
end
154+
EOF
155+
156+
run "$PROJECT_ROOT/scripts/update_homebrew_tap_formula.sh" \
157+
--formula "$formula_file" \
158+
--tag "V1.33.0" \
159+
--source-sha "new-source-sha" \
160+
--arm-sha "new-arm-sha" \
161+
--amd-sha "new-amd-sha"
162+
[ "$status" -eq 0 ]
163+
164+
run grep -q 'url "https://github.com/tw93/Mole/archive/refs/tags/V1.33.0.tar.gz"' "$formula_file"
165+
[ "$status" -eq 0 ]
166+
run grep -q 'sha256 "new-source-sha"' "$formula_file"
167+
[ "$status" -eq 0 ]
168+
run grep -q 'url "https://github.com/tw93/Mole/releases/download/V1.33.0/binaries-darwin-arm64.tar.gz"' "$formula_file"
169+
[ "$status" -eq 0 ]
170+
run grep -q 'sha256 "new-arm-sha"' "$formula_file"
171+
[ "$status" -eq 0 ]
172+
run grep -q 'url "https://github.com/tw93/Mole/releases/download/V1.33.0/binaries-darwin-amd64.tar.gz"' "$formula_file"
173+
[ "$status" -eq 0 ]
174+
run grep -q 'sha256 "new-amd-sha"' "$formula_file"
175+
[ "$status" -eq 0 ]
176+
}
177+
178+
@test "update_homebrew_tap_formula.sh fails when expected sections are missing" {
179+
local formula_file="$HOME/mole-missing-intel.rb"
180+
cat > "$formula_file" <<'EOF'
181+
class Mole < Formula
182+
desc "Mole"
183+
homepage "https://github.com/tw93/Mole"
184+
url "https://github.com/tw93/Mole/archive/refs/tags/V1.32.0.tar.gz"
185+
sha256 "old-source-sha"
186+
187+
on_arm do
188+
url "https://github.com/tw93/Mole/releases/download/V1.32.0/binaries-darwin-arm64.tar.gz"
189+
sha256 "old-arm-sha"
190+
end
191+
end
192+
EOF
193+
194+
run "$PROJECT_ROOT/scripts/update_homebrew_tap_formula.sh" \
195+
--formula "$formula_file" \
196+
--tag "V1.33.0" \
197+
--source-sha "new-source-sha" \
198+
--arm-sha "new-arm-sha" \
199+
--amd-sha "new-amd-sha"
200+
[ "$status" -ne 0 ]
201+
[[ "$output" == *"Failed to update formula"* ]]
202+
}

0 commit comments

Comments
 (0)