diff --git a/.github/workflows/studio-mac-update-smoke.yml b/.github/workflows/studio-mac-update-smoke.yml index cfa192b470..b65439f174 100644 --- a/.github/workflows/studio-mac-update-smoke.yml +++ b/.github/workflows/studio-mac-update-smoke.yml @@ -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 diff --git a/.github/workflows/studio-update-smoke.yml b/.github/workflows/studio-update-smoke.yml index b28e2bf0bd..057aeacbd4 100644 --- a/.github/workflows/studio-update-smoke.yml +++ b/.github/workflows/studio-update-smoke.yml @@ -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 diff --git a/.github/workflows/studio-windows-update-smoke.yml b/.github/workflows/studio-windows-update-smoke.yml index b412d60921..b477b3fa11 100644 --- a/.github/workflows/studio-windows-update-smoke.yml +++ b/.github/workflows/studio-windows-update-smoke.yml @@ -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 diff --git a/README.md b/README.md index 9e0bdb4dda..dc22804074 100644 --- a/README.md +++ b/README.md @@ -220,8 +220,8 @@ unsloth studio -p 8888 #### Uninstall The recommended way to fully remove Unsloth Studio is the matching uninstall script for your OS. It stops any running servers, removes the install dir, the launcher data dir, the desktop shortcut, and any platform-specific entries (macOS `.app` bundle + Launch Services on Mac; Start Menu, `HKCU\Software\Unsloth` registry key and user `PATH` entries on Windows): -* ​ **MacOS, WSL, Linux:** `curl -fsSL https://unsloth.ai/uninstall.sh | sh` -* ​ **Windows (PowerShell):** `irm https://unsloth.ai/uninstall.ps1 | iex` +* ​ **MacOS, WSL, Linux:** `curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.sh | sh` +* ​ **Windows (PowerShell):** `irm https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.ps1 | iex` If you only want to drop the install dir and keep the launcher/shortcut for a later reinstall, you can instead run `rm -rf ~/.unsloth/studio` (Mac/Linux/WSL) or `Remove-Item -Recurse -Force "$HOME\.unsloth\studio"` (Windows). The model cache at `~/.cache/huggingface` is not touched by any of these. diff --git a/uninstall.ps1 b/scripts/uninstall.ps1 similarity index 99% rename from uninstall.ps1 rename to scripts/uninstall.ps1 index 9dfe1bd83c..6174e7e494 100644 --- a/uninstall.ps1 +++ b/scripts/uninstall.ps1 @@ -4,8 +4,8 @@ # registry key. Honors custom roots set via UNSLOTH_STUDIO_HOME / STUDIO_HOME # at install time (read back from share\studio.conf). # -# Usage: irm https://raw.githubusercontent.com/unslothai/unsloth/main/uninstall.ps1 | iex -# Local: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; .\uninstall.ps1 +# Usage: irm https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.ps1 | iex +# Local: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; .\scripts\uninstall.ps1 function Uninstall-UnslothStudio { $ErrorActionPreference = "Continue" @@ -345,7 +345,7 @@ function Uninstall-UnslothStudio { Write-Host "If you installed Unsloth Studio with UNSLOTH_STUDIO_HOME or STUDIO_HOME" Write-Host "pointing at a custom directory, re-run this script with the same variable" Write-Host "set to also remove that install tree, e.g.:" - Write-Host " `$env:UNSLOTH_STUDIO_HOME = 'C:\your\path'; .\uninstall.ps1" + Write-Host " `$env:UNSLOTH_STUDIO_HOME = 'C:\your\path'; irm https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.ps1 | iex" } } diff --git a/uninstall.sh b/scripts/uninstall.sh similarity index 97% rename from uninstall.sh rename to scripts/uninstall.sh index 7fbdc8dfac..94ca04b204 100755 --- a/uninstall.sh +++ b/scripts/uninstall.sh @@ -5,7 +5,7 @@ # Honors custom roots set via UNSLOTH_STUDIO_HOME / STUDIO_HOME at # install time (read back from studio.conf). # -# Usage: curl -fsSL https://unsloth.ai/uninstall.sh | sh +# Usage: curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.sh | sh set -e @@ -279,5 +279,5 @@ if [ -z "${UNSLOTH_STUDIO_HOME:-}" ] && [ -z "${STUDIO_HOME:-}" ]; then echo "If you installed Unsloth Studio with UNSLOTH_STUDIO_HOME or STUDIO_HOME" echo "pointing at a custom directory, re-run this script with the same variable" echo "set to also remove that install tree, e.g.:" - echo " UNSLOTH_STUDIO_HOME=/your/path sh uninstall.sh" + echo " UNSLOTH_STUDIO_HOME=/your/path sh -c \"\$(curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.sh)\"" fi