Last active
October 1, 2024 14:50
-
-
Save Fronix/da7b33f92831087c1f4ef3ec4f111754 to your computer and use it in GitHub Desktop.
Meilisearch installer/updater for windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Provided as is | |
# Make sure to check the code! | |
# Folder for Meilisearch should include config.toml, this is not created automatically atm | |
# Script will require you to have the meilisearch binary exe on the filesystem | |
# IT WIL NOT FETCH FROM GITHUB | |
function Show-Menu { | |
Write-Host "=================================" | |
Write-Host " Meilisearch Management Program" | |
Write-Host "=================================" | |
Write-Host "1: Install Meilisearch" | |
Write-Host "2: Update Meilisearch" | |
Write-Host "3: Exit" | |
} | |
# Define the source path for WinSW.exe | |
$sourceWinSWPath = "C:\winsw\winsw.exe" | |
# Define the default base URI for Meilisearch | |
$defaultBaseUri = "http://localhost:7700/" | |
# Define the base URI for importing the dump | |
$baseUriImport = "http://localhost:7701/" | |
function Check-WinSW { | |
param ( | |
[string]$meilisearchDir | |
) | |
# Define the destination path for WinSW.exe in the Meilisearch directory | |
$winswPath = "$meilisearchDir\winsw.exe" | |
# Check if WinSW.exe exists in the destination directory | |
if (-Not (Test-Path -Path $winswPath)) { | |
# Try to copy from C:\winsw | |
if (Test-Path -Path $sourceWinSWPath) { | |
Copy-Item -Path $sourceWinSWPath -Destination $winswPath | |
Write-Host "Copied WinSW.exe to $meilisearchDir" | |
} else { | |
Write-Host "WinSW.exe not found in $meilisearchDir or C:\winsw. Please ensure it is available before proceeding." | |
Write-Host "Press any key to return to the main menu..." | |
[void][System.Console]::ReadKey($true) # Waits for the user to press a key | |
return $false | |
} | |
} | |
return $true | |
} | |
function WaitingForUser { | |
param ( | |
[switch]$ExitProgram # Optional switch parameter to exit the program | |
) | |
Write-Host "Press any key to continue..." | |
[void][System.Console]::ReadKey($true) # Waits for the user to press a key | |
if ($ExitProgram.IsPresent) { | |
Write-Host "Exiting the program..." | |
exit | |
} else { | |
return $false | |
} | |
} | |
function Install-Meilisearch { | |
# Step 1: Ask for the full path of the Meilisearch executable | |
$meilisearchPath = Read-Host "Enter the full path of the Meilisearch executable (including the executable name)" | |
# Step 2: Ask for the Meilisearch version | |
$meilisearchVersion = Read-Host "Enter the Meilisearch version (e.g., v1.10.0)" | |
# Step 3: Ask for the drive where Meilisearch should be installed | |
$installDrive = Read-Host "Enter the drive letter where Meilisearch should be installed (e.g., E:)" | |
# Step 4: Create the Meilisearch folder on the specified drive if it doesn't exist | |
$meilisearchDir = "$installDrive\Meilisearch" | |
if (-Not (Test-Path -Path $meilisearchDir)) { | |
New-Item -Path $meilisearchDir -ItemType Directory | |
Write-Host "Created directory: $meilisearchDir" | |
} | |
# Check if WinSW is installed before proceeding | |
if (-Not (Check-WinSW -meilisearchDir $meilisearchDir)) { | |
return | |
} | |
# Step 5: Create a version-specific folder within the Meilisearch directory | |
$versionDir = "$meilisearchDir\$meilisearchVersion" | |
if (-Not (Test-Path -Path $versionDir)) { | |
New-Item -Path $versionDir -ItemType Directory | |
Write-Host "Created directory: $versionDir" | |
} | |
# Step 6: Copy the executable to the version directory, rename it, and delete the original | |
$destinationPath = "$versionDir\meilisearch.exe" | |
Copy-Item -Path $meilisearchPath -Destination $destinationPath | |
Write-Host "Copied Meilisearch executable to $destinationPath" | |
Write-Host "Don't forget to delete the copied file $meilisearchPath" | |
# Step 7: Setup or update the Meilisearch service using WinSW | |
Setup-MeilisearchService $meilisearchDir $destinationPath $meilisearchVersion | |
WaitingForUser | |
} | |
function Update-Meilisearch { | |
# Check if WinSW is installed before proceeding | |
if (-Not (Check-WinSW)) { | |
return | |
} | |
# Step 1: Ask for the new Meilisearch version | |
$newVersion = Read-Host "Enter the new Meilisearch version (e.g., v1.10.0)" | |
# Step 2: Ask for the drive where Meilisearch is installed | |
$installDrive = Read-Host "Enter the drive letter where Meilisearch is installed (e.g., E:)" | |
# Step 3: Ask for the full path of the new Meilisearch executable | |
$newMeilisearchPath = Read-Host "Enter the full path of the new Meilisearch executable (including the executable name)" | |
# Step 4: Ask for the URL and API key of the Meilisearch instance to update | |
$meilisearchUrl = Read-Host "Enter the URL of the instance (leave empty for http://localhost:7700)" | |
if ([string]::IsNullOrEmpty($meilisearchUrl)) { | |
$meilisearchUrl = $defaultBaseUri | |
} | |
$apiKey = Read-Host "Enter the API key for the instance" | |
$meiliHealth = Check-MeiliHealth -meilisearchUrl $meilisearchUrl | |
if (-Not $meiliHealth) { | |
Write-Host "The old meilisearch instance is not running, start the service and try again." | |
WaitingForUser -ExitProgram | |
return | |
} | |
# Step 5: Update the Meilisearch folder with the new version | |
$meilisearchDir = "$installDrive\Meilisearch" | |
$newVersionDir = "$meilisearchDir\$newVersion" | |
if (-Not (Test-Path -Path $newVersionDir)) { | |
New-Item -Path $newVersionDir -ItemType Directory | |
Write-Host "Created directory: $newVersionDir" | |
} | |
# Check if WinSW is installed before proceeding | |
if (-Not (Check-WinSW -meilisearchDir $meilisearchDir)) { | |
return | |
} | |
try { | |
# Step 6: Copy the new executable to the new version directory, rename it, and delete the original | |
$destinationPath = "$newVersionDir\meilisearch.exe" | |
Copy-Item -Path $newMeilisearchPath -Destination $destinationPath | |
Write-Host "Copied new Meilisearch executable to $destinationPath" | |
} | |
catch { | |
Write-Host "Copy error: $_" | |
WaitingForUser -ExitProgram | |
} | |
# Step 7: Create a dump of the current Meilisearch instance | |
New-MeiliearchDump -apiKey $apiKey -baseUri $meilisearchUrl | |
# Step 8: Import the dump into the new Meilisearch instance | |
Import-MeilisearchDump -dumpDir "$meilisearchDir\dumps" -newMeilisearchPath $newVersionDir | |
# Remove-Item -Path $newMeilisearchPath | |
Write-Host "Don't forget to delete the copied file $meilisearchPath" | |
Read-Host "Import is done, ready to update the service. Press any key to continue..." | |
# Step 9: Update the Meilisearch service using WinSW | |
Setup-MeilisearchService $meilisearchDir $destinationPath $newVersion | |
# Step 10: Optionally, remove the old version directory or keep it for rollback | |
# Remove-Item -Path "$meilisearchDir\$currentVersion" -Recurse | |
Write-Host "Old version directory kept for rollback purposes" | |
WaitingForUser | |
} | |
function Check-MeiliHealth { | |
param ( | |
[string]$meilisearchUrl | |
) | |
$headers = @{ | |
"Content-Type" = "application/json" | |
} | |
if (-not $meilisearchUrl.EndsWith("/")) { | |
$meilisearchUrl = $meilisearchUrl + "/" | |
} | |
$healthUrl = $meilisearchUrl + "health" | |
try { | |
$healthResponse = Invoke-WebRequest -Uri $healthUrl -Method Get -Headers $headers | |
if ($healthResponse.StatusCode -eq 200) { | |
Write-Host "Meilisearch is healthy and running!" | |
return $true | |
} else { | |
Write-Host "Meilisearch is not running or healthy. Status code: $($healthResponse.StatusCode)" | |
return $false | |
} | |
} | |
catch { | |
return $false | |
} | |
} | |
function New-MeiliearchDump { | |
param ( | |
[string]$apiKey, | |
[string]$baseUri | |
) | |
# Step 1: Create a dump via Meilisearch API | |
$headers = @{ | |
"Authorization" = "Bearer $apiKey" | |
"Content-Type" = "application/json" | |
} | |
if (-not $baseUri.EndsWith("/")) { | |
$baseUri = $baseUri + "/" | |
} | |
$dumpsUri = $baseUri + "dumps" | |
$meiliHealth = Check-MeiliHealth -meilisearchUrl $baseUri | |
if (-Not $meiliHealth) { | |
Write-Host "The old meilisearch instance is not running, start the service and try again." | |
WaitingForUser -ExitProgram | |
return | |
} | |
try { | |
$dumpResponse = Invoke-RestMethod -Uri $dumpsUri -Method Post -Headers $headers | |
$taskId = $dumpResponse.taskUid | |
Write-Host "Dump creation initiated: $($dumpResponse.dumpUid)" | |
# Step 2: Wait for dump to be ready | |
while ($true) { | |
$tasksUri = $baseUri + "tasks/$taskId" | |
$statusResponse = Invoke-RestMethod -Uri $tasksUri -Method Get -Headers $headers | |
if ($statusResponse.status -eq "succeeded") { | |
Write-Host "Dump is ready!" | |
break | |
} elseif ($statusResponse.status -eq "failed" -or $statusResponse.status -eq "canceled") { | |
Write-Host "Dump creation failed!" | |
return | |
} | |
Write-Host "Dump is not ready yet, waiting..." | |
Start-Sleep -Seconds 5 | |
} | |
} | |
catch { | |
Write-Host "Error creating dump: $_" | |
WaitingForUser -ExitProgram | |
} | |
} | |
function Import-MeilisearchDump { | |
param ( | |
[string]$dumpDir, | |
[string]$newMeilisearchPath | |
) | |
$headers = @{ | |
"Content-Type" = "application/json" | |
} | |
# Get the latest dump file in the directory | |
$latestDump = Get-ChildItem -Path $dumpDir | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | |
try { | |
$baseUri = $baseUriImport | |
$healthUrl = $baseUri + "health" | |
# Step 1: Import the dump using Meilisearch binary | |
Write-Host "Starting dump import using the latest dump ($($latestDump.FullName))" | |
$meilisearchProcess = Start-Process -FilePath "meilisearch.exe" -WorkingDirectory $newMeilisearchPath -ArgumentList "--db-path", "./meili_db", "--import-dump", $latestDump.FullName, "--http-addr", "localhost:7701" -PassThru | |
Write-Host "Dump import started.... (Process ID: $($meilisearchProcess.Id))" | |
Write-Host "Waiting 10 seconds for the instance to start..." | |
Start-Sleep -Seconds 10 # Wait for the process to start | |
# Step 2: Wait for the dump to be fully loaded | |
Write-Host "Waiting for dump import to be processed..." | |
while ($true) { | |
try { | |
# Attempt to make a request to the health endpoint | |
$healthResponse = Invoke-WebRequest -Uri $healthUrl -Method Get -Headers $headers | |
# Check if the health response is successful (status code 200) | |
if ($healthResponse.StatusCode -eq 200) { | |
Write-Host "Dump import completed successfully! Stopping import instance..." | |
Stop-Process -Id $meilisearchProcess.Id -Force | |
break | |
} | |
} | |
catch { | |
# If there's a connection issue, catch the exception and continue trying | |
Write-Host "Connection failed, Still processing..." | |
} | |
# Wait before retrying | |
Start-Sleep -Seconds 5 | |
Write-Host "Still processing..." | |
} | |
} | |
catch { | |
Write-Host "Error importing dump: $_" | |
WaitingForUser -ExitProgram | |
} | |
} | |
function Setup-MeilisearchService { | |
param ( | |
[string]$meilisearchDir, | |
[string]$executablePath, | |
[string]$meilisearchVersion | |
) | |
# Define the service name as static and include the version in the description | |
$serviceName = "MeiliSearch" | |
$serviceDescription = "MeiliSearch Service - Version $meilisearchVersion" | |
$meilisearchConfigPath = "$meilisearchDir\config.toml" | |
$versionDir = "$meilisearchDir\$meilisearchVersion" | |
# Create the WinSW XML configuration file for the Meilisearch service with logging settings | |
$winswConfig = @" | |
<service> | |
<id>$serviceName</id> | |
<name>MeiliSearch</name> | |
<description>$serviceDescription</description> | |
<executable>$executablePath</executable> | |
<logpath>%BASE%\logs</logpath> | |
<arguments>"--config-file-path" ../config.toml "--db-path" ./meili_db</arguments> | |
<log mode="roll-by-time"> | |
<pattern>yyyyMMdd</pattern> | |
</log> | |
<startmode>automatic</startmode> | |
<priority>high</priority> | |
<workingdirectory>$versionDir</workingdirectory> | |
</service> | |
"@ | |
$winswConfigPath = "$meilisearchDir\meilisearch.xml" | |
$winswConfig | Out-File -FilePath $winswConfigPath -Encoding utf8 | |
$winswDir = $meilisearchDir | |
Write-Host "Created or updated WinSW service configuration file at $winswConfigPath" | |
# If the service already exists, stop it before updating | |
if (Get-Service -Name $serviceName -ErrorAction SilentlyContinue) { | |
# winsw stop $serviceName | |
& "$winswDir\winsw.exe" stop "$winswDir\meilisearch.xml" | |
Write-Host "Stopped existing Meilisearch service" | |
} | |
# Uninstall old service using WinSW | |
& "$winswDir\winsw.exe" uninstall "$winswDir\meilisearch.xml" | |
Write-Host "Uninstalled old Meilisearch service using WinSW" | |
# Install or update the service using WinSW | |
& "$winswDir\winsw.exe" install "$winswDir\meilisearch.xml" | |
Write-Host "Installed new Meilisearch service using WinSW" | |
# Start the service after installation/update | |
& "$winswDir\winsw.exe" start "$winswDir\meilisearch.xml" | |
Write-Host "Started Meilisearch service" | |
} | |
function Main { | |
while ($true) { | |
Show-Menu | |
$choice = Read-Host "Select an option" | |
switch ($choice) { | |
"1" { Install-Meilisearch } | |
"2" { Update-Meilisearch } | |
"3" { Write-Host "Exiting..."; exit } | |
default { Write-Host "Invalid option. Please try again." } | |
} | |
} | |
} | |
# Start the program | |
Main | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment