Move uninstall scripts into scripts/ and fix references (#5644)

* Move uninstall scripts into scripts/ and fix all references

Relocates `uninstall.sh` and `uninstall.ps1` from the repo root into
the existing `scripts/` directory, alongside the other helper scripts.

Reference fixes:
* `README.md`: Studio uninstall instructions now point at the raw
  GitHub URLs under `scripts/`. The previous `unsloth.ai/uninstall.*`
  short URLs currently 404 (unlike `unsloth.ai/install.sh`, which
  301s to the raw github URL), so the raw URL is the working entry
  point until that redirect is configured.
* `scripts/uninstall.sh` header `Usage:` example updated to the new
  raw GitHub path.
* `scripts/uninstall.ps1` header `Usage:` example updated to the new
  raw GitHub path.
* `.github/workflows/studio-update-smoke.yml`: `paths:` trigger and
  round-trip exec/exists checks now use `scripts/uninstall.sh`.
* `.github/workflows/studio-mac-update-smoke.yml`: same.
* `.github/workflows/studio-windows-update-smoke.yml`: `paths:`
  trigger and round-trip exec/exists checks now use
  `scripts/uninstall.ps1`.

The in-script help hints (e.g. `sh uninstall.sh`, `.\uninstall.ps1`)
are left unchanged because they are user-facing examples shown after
the user already has the file locally, and the basename form works
regardless of which directory the user downloaded the script into.

Follow-up note for unsloth.ai: once this lands, please add the
`unsloth.ai/uninstall.sh` and `unsloth.ai/uninstall.ps1` short-URL
redirects to `raw.githubusercontent.com/unslothai/unsloth/main/scripts/...`
(matching the existing `unsloth.ai/install.sh` redirect pattern).

* Update remaining uninstall script help hints for new scripts/ path

Three user-facing strings inside the uninstall scripts still showed
the old basename form, which became misleading after the move:

* `scripts/uninstall.ps1` header `# Local:` example: now references
  `.\scripts\uninstall.ps1` (the actual path from the cloned repo
  root).
* `scripts/uninstall.sh` env-var re-run hint: now shows the canonical
  curl-pipe form documented in README, since callers who came via
  `curl -fsSL ... | sh` never had a local `uninstall.sh` to invoke.
* `scripts/uninstall.ps1` env-var re-run hint: same, switched to the
  `irm ... | iex` form documented in README.

Pure string changes, no behavior change.

---------

Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
This commit is contained in:
Daniel Han 2026-05-20 04:42:03 -07:00 committed by GitHub
commit a74a1080e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 39 additions and 38 deletions

View file

@ -21,7 +21,7 @@ on:
pull_request:
paths:
- 'install.sh'
- 'uninstall.sh'
- 'scripts/uninstall.sh'
- 'studio/setup.sh'
- 'studio/install_python_stack.py'
- 'studio/install_llama_prebuilt.py'
@ -139,20 +139,20 @@ jobs:
echo "post-update Studio /api/health OK"
- name: Uninstall and verify clean
# Round-trip through uninstall.sh on real macOS. As a side effect
# this exercises the macOS-only .app bundle + Launch Services
# Round-trip through scripts/uninstall.sh on real macOS. As a side
# effect this exercises the macOS-only .app bundle + Launch Services
# removal path (~/Applications/Unsloth Studio.app, lsregister -u)
# which is not testable from a Linux runner. Skips gracefully if
# uninstall.sh has not landed yet (lets this workflow merge
# scripts/uninstall.sh has not landed yet (lets this workflow merge
# before #5497).
run: |
set -o pipefail
if [ ! -f uninstall.sh ]; then
echo "uninstall.sh not present in this tree; skipping round-trip"
if [ ! -f scripts/uninstall.sh ]; then
echo "scripts/uninstall.sh not present in this tree; skipping round-trip"
: > logs/uninstall.log
exit 0
fi
sh uninstall.sh 2>&1 | tee logs/uninstall.log
sh scripts/uninstall.sh 2>&1 | tee logs/uninstall.log
leak=0
for p in \
"$HOME/.unsloth/studio" \
@ -166,8 +166,8 @@ jobs:
fi
done
[ "$leak" -eq 0 ] || exit 1
sh uninstall.sh 2>&1 | tail -5
sh uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
echo "PASS: mac install -> update -> uninstall round-trip clean"
- name: Upload update logs

View file

@ -15,7 +15,7 @@ on:
pull_request:
paths:
- 'install.sh'
- 'uninstall.sh'
- 'scripts/uninstall.sh'
- 'studio/setup.sh'
- 'studio/install_python_stack.py'
- 'studio/install_llama_prebuilt.py'
@ -141,22 +141,22 @@ jobs:
echo "post-update Studio /api/health OK"
- name: Uninstall and verify clean
# Round-trip the installer through uninstall.sh: confirms the
# Round-trip the installer through scripts/uninstall.sh: confirms the
# uninstaller actually finds and removes everything install.sh +
# update wrote. Safety-guard scenarios (refuse-$HOME etc.) belong
# in a separate fast smoke job; this is the happy-path cleanup
# assertion that catches regressions where install.sh starts
# writing to a new location and uninstall.sh hasn't caught up.
# Skips gracefully if uninstall.sh has not landed yet (lets this
# workflow merge before #5497).
# writing to a new location and scripts/uninstall.sh hasn't caught up.
# Skips gracefully if scripts/uninstall.sh has not landed yet (lets
# this workflow merge before #5497).
run: |
set -o pipefail
if [ ! -f uninstall.sh ]; then
echo "uninstall.sh not present in this tree; skipping round-trip"
if [ ! -f scripts/uninstall.sh ]; then
echo "scripts/uninstall.sh not present in this tree; skipping round-trip"
: > logs/uninstall.log
exit 0
fi
sh uninstall.sh 2>&1 | tee logs/uninstall.log
sh scripts/uninstall.sh 2>&1 | tee logs/uninstall.log
leak=0
for p in \
"$HOME/.unsloth/studio" \
@ -171,8 +171,8 @@ jobs:
done
[ "$leak" -eq 0 ] || exit 1
# Idempotent: re-runs exit 0 on an empty $HOME.
sh uninstall.sh 2>&1 | tail -5
sh uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
echo "PASS: install -> update -> uninstall round-trip clean"
- name: Upload update logs

View file

@ -23,7 +23,7 @@ on:
pull_request:
paths:
- 'install.ps1'
- 'uninstall.ps1'
- 'scripts/uninstall.ps1'
- 'studio/setup.ps1'
- 'studio/setup.bat'
- 'studio/install_python_stack.py'
@ -268,21 +268,22 @@ jobs:
echo "post-update Studio /api/health OK"
- name: Uninstall and verify clean
# Round-trip through uninstall.ps1 against the default install
# tree at %USERPROFILE%\.unsloth\studio. Catches regressions
# where install.ps1 starts writing under a new key (registry,
# Start Menu, %APPDATA%) and uninstall.ps1 has not been updated
# to match. Skips gracefully if uninstall.ps1 has not landed yet
# (lets this workflow merge before #5513).
# Round-trip through scripts/uninstall.ps1 against the default
# install tree at %USERPROFILE%\.unsloth\studio. Catches
# regressions where install.ps1 starts writing under a new key
# (registry, Start Menu, %APPDATA%) and scripts/uninstall.ps1 has
# not been updated to match. Skips gracefully if
# scripts/uninstall.ps1 has not landed yet (lets this workflow
# merge before #5513).
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path logs | Out-Null
if (-not (Test-Path "$PWD\uninstall.ps1")) {
Write-Host "uninstall.ps1 not present in this tree; skipping round-trip"
if (-not (Test-Path "$PWD\scripts\uninstall.ps1")) {
Write-Host "scripts/uninstall.ps1 not present in this tree; skipping round-trip"
"" | Set-Content logs/uninstall.log
exit 0
}
pwsh -NoProfile -File "$PWD\uninstall.ps1" *>&1 | Tee-Object -FilePath logs/uninstall.log
pwsh -NoProfile -File "$PWD\scripts\uninstall.ps1" *>&1 | Tee-Object -FilePath logs/uninstall.log
$leak = 0
foreach ($p in @(
"$env:USERPROFILE\.unsloth\studio",
@ -296,8 +297,8 @@ jobs:
}
if ($leak -gt 0) { exit 1 }
# Idempotency.
pwsh -NoProfile -File "$PWD\uninstall.ps1" *>&1 | Select-Object -Last 5
pwsh -NoProfile -File "$PWD\uninstall.ps1" *>&1 | Select-Object -Last 5
pwsh -NoProfile -File "$PWD\scripts\uninstall.ps1" *>&1 | Select-Object -Last 5
pwsh -NoProfile -File "$PWD\scripts\uninstall.ps1" *>&1 | Select-Object -Last 5
Write-Host "PASS: windows install -> update -> uninstall round-trip clean"
- name: Upload update logs