mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-04-22 07:28:43 -04:00
[ENG-265] Improve setup scripts (#1368)
* Setup script revamp * Move toml to dev dep + CI runs the postinstall in debug mode * Fix windows CI * chmod +x scripts/setup.sh * Fix eslint and ts CI * Remove binstall + Fix trying to read input in CI * Doesn't need to check pnpm and rust in CI * Run postinstall script for Clippy CI * Attempt to fix windows CI not running postinstall - Ignore cache when running postinstall on CI * commited generated config.toml by mistake * Pass GITHUB_TOKEN to `pnpm i` * Update archive-wasm + Increase minimum node version to 18.17 * CI: Move rust setup after post-install script * Revert: CI: Move rust setup after post-install script * Fix CI, generate dummy cargo config.toml to fix prisma generation * Fix windows CI * CI: Fix wrong command --------- Co-authored-by: Utku <74243531+utkubakir@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
fe1350d70d
commit
bd0a7ff434
432
.github/scripts/setup-system.ps1
vendored
432
.github/scripts/setup-system.ps1
vendored
@@ -1,432 +0,0 @@
|
||||
# Set default value of 0 for external command exit code
|
||||
$LASTEXITCODE = 0
|
||||
# Enables strict mode, which causes PowerShell to treat uninitialized variables, undefined functions, and other common errors as terminating errors.
|
||||
$ErrorActionPreference = if ($env:CI) { 'Stop' } else { 'Inquire' }
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
function Reset-Path {
|
||||
$env:Path = [System.Environment]::ExpandEnvironmentVariables(
|
||||
[System.Environment]::GetEnvironmentVariable('Path', 'Machine') +
|
||||
[IO.Path]::PathSeparator +
|
||||
[System.Environment]::GetEnvironmentVariable('Path', 'User')
|
||||
)
|
||||
}
|
||||
|
||||
# Verify if environment is Windows 64-bit and if the user is an administrator
|
||||
if ((-not [string]::IsNullOrEmpty($env:PROCESSOR_ARCHITEW6432)) -or (
|
||||
"$env:PROCESSOR_ARCHITECTURE" -eq 'ARM64'
|
||||
) -or (
|
||||
-not [System.Environment]::Is64BitOperatingSystem
|
||||
# Powershell >= 6 is cross-platform, check if running on Windows
|
||||
) -or (($PSVersionTable.PSVersion.Major -ge 6) -and (-not $IsWindows))
|
||||
) {
|
||||
$ErrorActionPreference = 'Continue'
|
||||
Write-Host # There is no oficial ffmpeg binaries for Windows 32 or ARM
|
||||
if (Test-Path "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe" -PathType Leaf) {
|
||||
throw 'You are using PowerShell (32-bit), please re-run in PowerShell (64-bit)'
|
||||
} else {
|
||||
throw 'This script is only supported on Windows 64-bit'
|
||||
}
|
||||
Exit 1
|
||||
} elseif (
|
||||
-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
) {
|
||||
# Start a new PowerShell process with administrator privileges and set the working directory to the directory where the script is located
|
||||
$proc = Start-Process -PassThru -Wait -FilePath 'PowerShell.exe' -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Definition)`"" -WorkingDirectory "$PSScriptRoot"
|
||||
# Reset path so the user doesn't have to restart the shell to use the tools installed by this script
|
||||
Reset-Path
|
||||
Exit $proc.ExitCode
|
||||
}
|
||||
|
||||
function Exit-WithError($err, $help = $null) {
|
||||
if ($null -ne $help) {
|
||||
Write-Host
|
||||
Write-Host $help -ForegroundColor DarkRed
|
||||
}
|
||||
throw $err
|
||||
Exit 1
|
||||
}
|
||||
|
||||
function Add-DirectoryToPath($directory) {
|
||||
Reset-Path
|
||||
if ($env:Path.Split([IO.Path]::PathSeparator) -notcontains $directory) {
|
||||
[System.Environment]::SetEnvironmentVariable(
|
||||
'Path',
|
||||
[System.Environment]::GetEnvironmentVariable('Path', 'User') + [IO.Path]::PathSeparator + $directory,
|
||||
'User'
|
||||
)
|
||||
|
||||
if ($env:CI) {
|
||||
# If running in CI, we need to use GITHUB_PATH instead of the normal PATH env variables
|
||||
Add-Content $env:GITHUB_PATH "$directory`n"
|
||||
}
|
||||
}
|
||||
Reset-Path
|
||||
}
|
||||
|
||||
$ghUrl = 'https://api.github.com/repos'
|
||||
$sdGhPath = 'spacedriveapp/spacedrive'
|
||||
|
||||
function Invoke-RestMethodGithub {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Uri,
|
||||
[string]$Method = 'GET',
|
||||
[string]$OutFile = $null,
|
||||
[hashtable]$Headers = @{},
|
||||
[string]$UserAgent = 'PowerShell'
|
||||
)
|
||||
|
||||
$headers.Add('Accept', 'application/vnd.github+json')
|
||||
$headers.Add('X-GitHub-Api-Version', '2022-11-28')
|
||||
|
||||
if (![string]::IsNullOrEmpty($env:GITHUB_TOKEN)) {
|
||||
$headers.Add('Authorization', "Bearer $($env:GITHUB_TOKEN)")
|
||||
}
|
||||
|
||||
$params = @{
|
||||
Uri = $Uri
|
||||
Method = $Method
|
||||
OutFile = $OutFile
|
||||
Headers = $Headers
|
||||
UserAgent = $UserAgent
|
||||
}
|
||||
|
||||
Invoke-RestMethod @params
|
||||
}
|
||||
|
||||
function DownloadArtifact {
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$ArtifactPath,
|
||||
[string]$OutFile
|
||||
)
|
||||
|
||||
try {
|
||||
Invoke-RestMethodGithub -Uri "$ghUrl/$sdGhPath/actions/artifacts/$($($ArtifactPath -split '/')[3])/zip" -OutFile $OutFile
|
||||
} catch {
|
||||
# nightly.link is a workaround for the lack of a public GitHub API to download artifacts from a workflow run
|
||||
# https://github.com/actions/upload-artifact/issues/51
|
||||
# Use it when running in environments that are not authenticated with GitHub
|
||||
Write-Host 'Failed to download artifact from Github, falling back to nightly.link' -ForegroundColor Yellow
|
||||
Invoke-RestMethodGithub -Uri "https://nightly.link/${sdGhPath}/${ArtifactPath}" -OutFile $OutFile
|
||||
}
|
||||
}
|
||||
|
||||
# Reset PATH to ensure the script doesn't have stale Path entries
|
||||
Reset-Path
|
||||
|
||||
# Get temp folder
|
||||
$temp = [System.IO.Path]::GetTempPath()
|
||||
|
||||
# Get project dir (get grandparent dir from script location: <PROJECT_ROOT>\.github\scripts)
|
||||
$projectRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
|
||||
$packageJson = Get-Content -Raw -Path "$projectRoot\package.json" | ConvertFrom-Json
|
||||
|
||||
# Valid winget exit status
|
||||
$wingetValidExit = 0, -1978335189, -1978335153, -1978335135
|
||||
|
||||
# Currently LLVM >= 16 is not supported due to incompatibilities with ffmpeg-sys-next
|
||||
# See https://github.com/spacedriveapp/spacedrive/issues/677
|
||||
$llvmVersion = [Version]'15.0.7'
|
||||
|
||||
$ffmpegVersion = '6.0'
|
||||
|
||||
# Change CWD to project root
|
||||
Set-Location $projectRoot
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$projectRoot\.cargo\config"
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$projectRoot\target\Frameworks" -Recurse
|
||||
|
||||
Write-Host 'Spacedrive Development Environment Setup' -ForegroundColor Magenta
|
||||
Write-Host @"
|
||||
|
||||
To set up your machine for Spacedrive development, this script will do the following:
|
||||
1) Install Windows C++ build tools
|
||||
2) Install Edge Webview 2
|
||||
3) Install Rust and Cargo
|
||||
4) Install Rust tools
|
||||
5) Install Strawberry perl (used by to build the openssl-sys crate)
|
||||
6) Install Node.js, npm and pnpm
|
||||
7) Install LLVM $llvmVersion (compiler for ffmpeg-rust)
|
||||
8) Download the protbuf compiler
|
||||
9) Download a compatible ffmpeg build
|
||||
"@
|
||||
|
||||
# Install System dependencies (GitHub Actions already has all of those installed)
|
||||
if (-not $env:CI) {
|
||||
if (-not (Get-Command winget -ea 0)) {
|
||||
Exit-WithError 'winget not available' @'
|
||||
Follow the instructions here to install winget:
|
||||
https://learn.microsoft.com/windows/package-manager/winget/
|
||||
'@
|
||||
}
|
||||
|
||||
# Check system winget version is greater or equal to v1.4.10052
|
||||
$wingetVersion = [Version]((winget --version) -replace '.*?(\d+)\.(\d+)\.(\d+).*', '$1.$2.$3')
|
||||
$requiredVersion = [Version]'1.4.10052'
|
||||
if ($wingetVersion.CompareTo($requiredVersion) -lt 0) {
|
||||
$errorMessage = "You need to update your winget to version $requiredVersion or higher."
|
||||
Exit-WithError $errorMessage
|
||||
}
|
||||
|
||||
# Check connectivity to GitHub
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
if (-not ((Test-NetConnection -ComputerName 'github.com' -Port 80).TcpTestSucceeded)) {
|
||||
Exit-WithError "Can't connect to github, check your internet connection and run this script again"
|
||||
}
|
||||
$ProgressPreference = 'Continue'
|
||||
|
||||
Write-Host
|
||||
Read-Host 'Press Enter to continue'
|
||||
|
||||
# TODO: Force update Visual Studio build tools
|
||||
Write-Host
|
||||
Write-Host 'Installing Visual Studio Build Tools...' -ForegroundColor Yellow
|
||||
Write-Host 'This will take some time as it involves downloading several gigabytes of data....' -ForegroundColor Cyan
|
||||
winget install -e --accept-source-agreements --force --disable-interactivity --id Microsoft.VisualStudio.2022.BuildTools `
|
||||
--override 'updateall --quiet --wait'
|
||||
# Force install because BuildTools is itself a package manager, so let it decide if something needs to be installed or not
|
||||
winget install -e --accept-source-agreements --force --disable-interactivity --id Microsoft.VisualStudio.2022.BuildTools `
|
||||
--override '--wait --quiet --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended'
|
||||
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
|
||||
Exit-WithError 'Failed to install Visual Studio Build Tools'
|
||||
} else {
|
||||
$LASTEXITCODE = 0
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing Edge Webview 2...' -ForegroundColor Yellow
|
||||
# This is normally already available, but on some early Windows 10 versions it isn't
|
||||
winget install -e --accept-source-agreements --disable-interactivity --id Microsoft.EdgeWebView2Runtime
|
||||
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
|
||||
Exit-WithError 'Failed to install Edge Webview 2'
|
||||
} else {
|
||||
$LASTEXITCODE = 0
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing Rust and Cargo...' -ForegroundColor Yellow
|
||||
winget install -e --accept-source-agreements --disable-interactivity --id Rustlang.Rustup
|
||||
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
|
||||
Exit-WithError 'Failed to install Rust and Cargo'
|
||||
} else {
|
||||
$LASTEXITCODE = 0
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing Strawberry perl...' -ForegroundColor Yellow
|
||||
winget install -e --accept-source-agreements --disable-interactivity --id StrawberryPerl.StrawberryPerl
|
||||
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
|
||||
Exit-WithError 'Failed to install Strawberry perl'
|
||||
} else {
|
||||
$LASTEXITCODE = 0
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing NodeJS...' -ForegroundColor Yellow
|
||||
# Check if Node.JS is already installed and if it's compatible with the project
|
||||
$currentNode = Get-Command node -ea 0
|
||||
$currentNodeVersion = if (-not $currentNode) { $null } elseif ($currentNode.Version) { $currentNode.Version } elseif ((node --version) -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
|
||||
$enginesNodeVersion = if ($packageJson.engines.node -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
|
||||
if ($currentNodeVersion -and $enginesNodeVersion -and $currentNodeVersion.CompareTo($enginesNodeVersion) -lt 0) {
|
||||
Exit-WithError "Current Node.JS version: $currentNodeVersion (required: $enginesNodeVersion)" `
|
||||
'Uninstall the current version of Node.JS and run this script again'
|
||||
}
|
||||
# Install Node.JS
|
||||
winget install -e --accept-source-agreements --disable-interactivity --id OpenJS.NodeJS
|
||||
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
|
||||
Exit-WithError 'Failed to install NodeJS'
|
||||
} else {
|
||||
$LASTEXITCODE = 0
|
||||
}
|
||||
# Add NodeJS to the PATH
|
||||
Add-DirectoryToPath "$env:SystemDrive\Program Files\nodejs"
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Checking for LLVM...' -ForegroundColor Yellow
|
||||
# Check if LLVM is already installed and if it's compatible with the project
|
||||
$currentLLVMVersion = if ("$(winget list -e --disable-interactivity --id LLVM.LLVM)" -match '(?sm)LLVM.LLVM\s+(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
|
||||
if ($currentLLVMVersion -and $currentLLVMVersion.Major -gt $llvmVersion.Major) {
|
||||
Exit-WithError "Current LLVM version: $currentLLVMVersion (required: $llvmVersion)" `
|
||||
'Uninstall the current version of LLVM and run this script again'
|
||||
}
|
||||
# Install LLVM
|
||||
winget install -e --accept-source-agreements --disable-interactivity --id LLVM.LLVM --version "$llvmVersion"
|
||||
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
|
||||
Exit-WithError 'Failed to install NodeJS'
|
||||
} else {
|
||||
$LASTEXITCODE = 0
|
||||
}
|
||||
# Add LLVM to the PATH
|
||||
Add-DirectoryToPath "$env:SystemDrive\Program Files\LLVM\bin"
|
||||
|
||||
# Reset Path to ensure that executable installed above are available to rest of the script
|
||||
Reset-Path
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing Rust MSVC Toolchain...' -ForegroundColor Yellow
|
||||
rustup toolchain install stable-msvc
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Exit-WithError 'Failed to install Rust MSVC Toolchain'
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing Rust tools...' -ForegroundColor Yellow
|
||||
cargo install cargo-watch
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Exit-WithError 'Failed to install Rust tools'
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Installing for pnpm...' -ForegroundColor Yellow
|
||||
# Check if pnpm is already installed and if it's compatible with the project
|
||||
$currentPnpmVersion = if (-not (Get-Command pnpm -ea 0)) { $null } elseif ((pnpm --version) -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
|
||||
$enginesPnpmVersion = if ($packageJson.engines.pnpm -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
|
||||
|
||||
if (-not $currentPnpmVersion) {
|
||||
# Remove possible remaining envvars from old pnpm installation
|
||||
[System.Environment]::SetEnvironmentVariable('PNPM_HOME', $null, [System.EnvironmentVariableTarget]::Machine)
|
||||
[System.Environment]::SetEnvironmentVariable('PNPM_HOME', $null, [System.EnvironmentVariableTarget]::User)
|
||||
|
||||
# Install pnpm
|
||||
npm install -g "pnpm@latest-$($enginesPnpmVersion.Major)"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Exit-WithError 'Failed to install pnpm'
|
||||
}
|
||||
|
||||
# Add NPM global modules to the PATH
|
||||
if (Test-Path "$env:APPDATA\npm" -PathType Container) {
|
||||
Add-DirectoryToPath "$env:APPDATA\npm"
|
||||
}
|
||||
} elseif ($currentPnpmVersion -and $enginesPnpmVersion -and $currentPnpmVersion.CompareTo($enginesPnpmVersion) -lt 0) {
|
||||
Exit-WithError "Current pnpm version: $currentPnpmVersion (required: $enginesPnpmVersion)" `
|
||||
'Uninstall the current version of pnpm and run this script again'
|
||||
}
|
||||
}
|
||||
|
||||
# Create target folder, continue if already exists
|
||||
New-Item -Force -ErrorAction SilentlyContinue -ItemType Directory -Path "$projectRoot\target\Frameworks" | Out-Null
|
||||
|
||||
# --
|
||||
|
||||
Write-Host
|
||||
Write-Host 'Retrieving protobuf build...' -ForegroundColor Yellow
|
||||
|
||||
$filename = $null
|
||||
$downloadUri = $null
|
||||
$releasesUri = "${ghUrl}/protocolbuffers/protobuf/releases"
|
||||
$filenamePattern = '*-win64.zip'
|
||||
|
||||
$releases = Invoke-RestMethodGithub -Uri $releasesUri
|
||||
for ($i = 0; $i -lt $releases.Count; $i++) {
|
||||
$release = $releases[$i]
|
||||
foreach ($asset in $release.assets) {
|
||||
if ($asset.name -like $filenamePattern) {
|
||||
$filename = $asset.name
|
||||
$downloadUri = $asset.browser_download_url
|
||||
$i = $releases.Count
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not ($filename -and $downloadUri)) {
|
||||
Exit-WithError "Couldn't find a protobuf compiler installer"
|
||||
}
|
||||
|
||||
Write-Host "Dowloading protobuf zip from ${downloadUri}..." -ForegroundColor Yellow
|
||||
Invoke-RestMethodGithub -Uri $downloadUri -OutFile "$temp\protobuf.zip"
|
||||
|
||||
Write-Host 'Expanding protobuf zip...' -ForegroundColor Yellow
|
||||
Expand-Archive "$temp\protobuf.zip" "$projectRoot\target\Frameworks" -Force
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$temp\protobuf.zip"
|
||||
|
||||
# --
|
||||
|
||||
Write-Host "Retrieving ffmpeg-${ffmpegVersion} build..." -ForegroundColor Yellow
|
||||
|
||||
$page = 1
|
||||
while ($page -gt 0) {
|
||||
$success = ''
|
||||
Invoke-RestMethodGithub -Uri `
|
||||
"${ghUrl}/${sdGhPath}/actions/workflows/ffmpeg-windows.yml/runs?page=$page&per_page=100&status=success" `
|
||||
| ForEach-Object {
|
||||
if (-not $_.workflow_runs) {
|
||||
Exit-WithError "Error: $_"
|
||||
}
|
||||
|
||||
$_.workflow_runs | ForEach-Object {
|
||||
$artifactPath = (
|
||||
(Invoke-RestMethodGithub -Uri ($_.artifacts_url | Out-String) -Method Get).artifacts `
|
||||
| Where-Object {
|
||||
$_.name -eq "ffmpeg-${ffmpegVersion}-x86_64"
|
||||
} | ForEach-Object {
|
||||
$id = $_.id
|
||||
$workflowRunId = $_.workflow_run.id
|
||||
"suites/${workflowRunId}/artifacts/${id}"
|
||||
} | Select-Object -First 1
|
||||
)
|
||||
|
||||
try {
|
||||
if ([string]::IsNullOrEmpty($artifactPath)) {
|
||||
throw 'Empty argument'
|
||||
}
|
||||
|
||||
# Download and extract the artifact
|
||||
Write-Host "Dowloading ffmpeg-${ffmpegVersion} zip from artifact ${artifactPath}..." -ForegroundColor Yellow
|
||||
|
||||
DownloadArtifact -ArtifactPath $artifactPath -OutFile "$temp/ffmpeg.zip"
|
||||
|
||||
Write-Host "Expanding ffmpeg-${ffmpegVersion} zip..." -ForegroundColor Yellow
|
||||
Expand-Archive "$temp/ffmpeg.zip" "$projectRoot\target\Frameworks" -Force
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$temp/ffmpeg.zip"
|
||||
|
||||
$success = 'yes'
|
||||
break
|
||||
} catch {
|
||||
$errorMessage = $_.Exception.Message
|
||||
Write-Host "Error: $errorMessage" -ForegroundColor Red
|
||||
Write-Host 'Failed to download ffmpeg artifact release, trying again in 1sec...'
|
||||
Start-Sleep -Seconds 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($success -eq 'yes') {
|
||||
break
|
||||
}
|
||||
|
||||
$page++
|
||||
Write-Output 'ffmpeg artifact not found, trying again in 1sec...'
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
|
||||
if ($success -ne 'yes') {
|
||||
Exit-WithError 'Failed to download ffmpeg files'
|
||||
}
|
||||
|
||||
@(
|
||||
'[env]',
|
||||
"PROTOC = `"$("$projectRoot\target\Frameworks\bin\protoc" -replace '\\', '\\')`"",
|
||||
"FFMPEG_DIR = `"$("$projectRoot\target\Frameworks" -replace '\\', '\\')`"",
|
||||
'',
|
||||
'[target.x86_64-pc-windows-msvc]',
|
||||
"rustflags = [`"-L`", `"$("$projectRoot\target\Frameworks\lib" -replace '\\', '\\')`"]",
|
||||
'',
|
||||
(Get-Content "$projectRoot\.cargo\config.toml" -Encoding utf8)
|
||||
) | Out-File -Force -Encoding utf8 -FilePath "$projectRoot\.cargo\config"
|
||||
|
||||
if (-not $env:CI) {
|
||||
Write-Host
|
||||
Write-Host 'Your machine has been setup for Spacedrive development!' -ForegroundColor Green
|
||||
Write-Host 'You will need to re-run this script if there are rust dependencies changes or you use `pnpm clean` or `cargo clean`!' -ForegroundColor Red
|
||||
Write-Host
|
||||
Read-Host 'Press Enter to continue'
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Exit-WithError "Something went wrong, exit code: $LASTEXITCODE"
|
||||
}
|
||||
428
.github/scripts/setup-system.sh
vendored
428
.github/scripts/setup-system.sh
vendored
@@ -1,428 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${CI:-}" = "true" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Force xz to use multhreaded extraction
|
||||
export XZ_OPT='-T0'
|
||||
|
||||
SYSNAME="$(uname)"
|
||||
FFMPEG_VERSION='6.0'
|
||||
|
||||
err() {
|
||||
for _line in "$@"; do
|
||||
echo "$@" >&2
|
||||
done
|
||||
exit 1
|
||||
}
|
||||
|
||||
has() {
|
||||
if [ "$#" -ne 1 ]; then
|
||||
err "Usage: has <command>"
|
||||
fi
|
||||
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
_gh_url="https://api.github.com/repos"
|
||||
_sd_gh_path='spacedriveapp/spacedrive'
|
||||
gh_curl() {
|
||||
if [ "$#" -ne 1 ]; then
|
||||
err "Usage: gh_curl <api_route>"
|
||||
fi
|
||||
|
||||
url="$1"
|
||||
|
||||
# Required headers for GitHub API
|
||||
set -- -LSs -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28"
|
||||
|
||||
# Add authorization header if GITHUB_TOKEN is set, to avoid being rate limited
|
||||
if [ -n "${GITHUB_TOKEN:-}" ]; then
|
||||
set -- "$@" -H "Authorization: Bearer $GITHUB_TOKEN"
|
||||
fi
|
||||
|
||||
curl "$@" "$url"
|
||||
}
|
||||
|
||||
script_failure() {
|
||||
if [ -n "${1:-}" ]; then
|
||||
_line="on line $1"
|
||||
else
|
||||
_line="(unknown)"
|
||||
fi
|
||||
err "An error occurred $_line." "Setup failed."
|
||||
}
|
||||
|
||||
trap 'script_failure ${LINENO:-}' ERR
|
||||
|
||||
echo "Setting up this system for Spacedrive development."
|
||||
echo
|
||||
|
||||
# Change CWD to the directory of this script
|
||||
CDPATH='' cd -- "$(dirname -- "$0")"
|
||||
_script_path="$(pwd -P)"
|
||||
_cargo_config="${_script_path}/../../.cargo"
|
||||
|
||||
rm -rf "$_cargo_config/config"
|
||||
|
||||
if ! has cargo; then
|
||||
err 'Rust was not found.' \
|
||||
"Ensure the 'rustc' and 'cargo' binaries are in your \$PATH." \
|
||||
'https://rustup.rs'
|
||||
fi
|
||||
|
||||
if [ "${CI:-}" != "true" ] && [ "${spacedrive_skip_pnpm_check:-}" != "true" ]; then
|
||||
echo "checking for pnpm..."
|
||||
|
||||
if ! has pnpm; then
|
||||
err 'pnpm was not found.' \
|
||||
"Ensure the 'pnpm' command is in your \$PATH." \
|
||||
'You must use pnpm for this project; yarn and npm are not allowed.' \
|
||||
'https://pnpm.io/installation'
|
||||
else
|
||||
echo "found pnpm!"
|
||||
fi
|
||||
else
|
||||
echo "Skipping pnpm check."
|
||||
fi
|
||||
|
||||
if [ "${CI:-}" != "true" ]; then
|
||||
echo "Installing Rust tools"
|
||||
cargo install cargo-watch
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
if [ "${1:-}" = "mobile" ]; then
|
||||
echo "Setting up for mobile development."
|
||||
|
||||
# iOS targets
|
||||
if [ "$SYSNAME" = "Darwin" ]; then
|
||||
echo "Checking for Xcode..."
|
||||
if ! /usr/bin/xcodebuild -version >/dev/null; then
|
||||
err "Xcode was not detected." \
|
||||
"Please ensure Xcode is installed and try again."
|
||||
fi
|
||||
|
||||
echo "Installing iOS targets for Rust..."
|
||||
|
||||
rustup target add aarch64-apple-ios
|
||||
rustup target add aarch64-apple-ios-sim
|
||||
rustup target add x86_64-apple-ios # for CI
|
||||
fi
|
||||
|
||||
# Android requires python
|
||||
if ! command -v python3 >/dev/null; then
|
||||
err 'python3 was not found.' \
|
||||
'This is required for Android mobile development.' \
|
||||
"Ensure 'python3' is available in your \$PATH and try again."
|
||||
fi
|
||||
|
||||
# Android targets
|
||||
echo "Setting up Android targets for Rust..."
|
||||
|
||||
rustup target add armv7-linux-androideabi # for arm
|
||||
rustup target add aarch64-linux-android # for arm64
|
||||
rustup target add i686-linux-android # for x86
|
||||
rustup target add x86_64-linux-android # for x86_64
|
||||
rustup target add x86_64-unknown-linux-gnu # for linux-x86-64
|
||||
rustup target add aarch64-apple-darwin # for darwin arm64 (if you have an M1 Mac)
|
||||
rustup target add x86_64-apple-darwin # for darwin x86_64 (if you have an Intel Mac)
|
||||
rustup target add x86_64-pc-windows-gnu # for win32-x86-64-gnu
|
||||
rustup target add x86_64-pc-windows-msvc # for win32-x86-64-msvc
|
||||
|
||||
echo "Done setting up mobile targets."
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ "$SYSNAME" = "Linux" ]; then
|
||||
if has apt-get; then
|
||||
echo "Detected apt!"
|
||||
echo "Installing dependencies with apt..."
|
||||
|
||||
# Tauri dependencies
|
||||
DEBIAN_TAURI_DEPS="libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev patchelf"
|
||||
|
||||
# FFmpeg dependencies
|
||||
DEBIAN_FFMPEG_DEPS="libheif-dev libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev ffmpeg"
|
||||
|
||||
# Webkit2gtk requires gstreamer plugins for video playback to work
|
||||
DEBIAN_VIDEO_DEPS="gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-libav gstreamer1.0-pipewire gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-pulseaudio gstreamer1.0-vaapi libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev"
|
||||
|
||||
# Bindgen dependencies - it's used by a dependency of Spacedrive
|
||||
DEBIAN_BINDGEN_DEPS="pkg-config clang"
|
||||
|
||||
# Protobuf compiler
|
||||
DEBIAN_LIBP2P_DEPS="protobuf-compiler"
|
||||
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install ${SPACEDRIVE_CUSTOM_APT_FLAGS:-} $DEBIAN_TAURI_DEPS $DEBIAN_FFMPEG_DEPS $DEBIAN_BINDGEN_DEPS $DEBIAN_LIBP2P_DEPS $DEBIAN_VIDEO_DEPS
|
||||
elif has pacman; then
|
||||
echo "Detected pacman!"
|
||||
echo "Installing dependencies with pacman..."
|
||||
|
||||
# Tauri deps https://tauri.studio/guides/getting-started/setup/linux#1-system-dependencies
|
||||
ARCH_TAURI_DEPS="webkit2gtk base-devel curl wget openssl appmenu-gtk-module gtk3 libappindicator-gtk3 librsvg libvips patchelf"
|
||||
|
||||
# Webkit2gtk requires gstreamer plugins for video playback to work
|
||||
ARCH_VIDEO_DEPS="gst-libav gst-plugins-bad gst-plugins-base gst-plugins-good gst-plugins-ugly gst-plugin-pipewire gstreamer-vaapi"
|
||||
|
||||
# FFmpeg dependencies
|
||||
ARCH_FFMPEG_DEPS="libheif ffmpeg"
|
||||
|
||||
# Bindgen dependencies - it's used by a dependency of Spacedrive
|
||||
ARCH_BINDGEN_DEPS="clang"
|
||||
|
||||
# Protobuf compiler - https://github.com/archlinux/svntogit-packages/blob/packages/protobuf/trunk/PKGBUILD provides `libprotoc`
|
||||
ARCH_LIBP2P_DEPS="protobuf"
|
||||
|
||||
sudo pacman -Sy --needed $ARCH_TAURI_DEPS $ARCH_FFMPEG_DEPS $ARCH_BINDGEN_DEPS $ARCH_LIBP2P_DEPS $ARCH_VIDEO_DEPS
|
||||
elif has dnf; then
|
||||
echo "Detected dnf!"
|
||||
echo "Installing dependencies with dnf..."
|
||||
|
||||
# `webkit2gtk4.0-devel` also provides `webkit2gtk3-devel`, it's just under a different package in fedora versions >= 37.
|
||||
# https://koji.fedoraproject.org/koji/packageinfo?tagOrder=-blocked&packageID=26162#taglist
|
||||
# https://packages.fedoraproject.org/pkgs/webkitgtk/webkit2gtk4.0-devel/fedora-38.html#provides
|
||||
FEDORA_37_TAURI_WEBKIT="webkit2gtk4.0-devel"
|
||||
FEDORA_36_TAURI_WEBKIT="webkit2gtk3-devel"
|
||||
|
||||
# Tauri dependencies
|
||||
# openssl is manually declared here as i don't think openssl and openssl-devel are actually dependant on eachother
|
||||
# openssl also has a habit of being missing from some of my fresh Fedora installs - i've had to install it at least twice
|
||||
FEDORA_TAURI_DEPS="openssl openssl-devel curl wget libappindicator-gtk3 librsvg2-devel patchelf"
|
||||
|
||||
# required for building the openssl-sys crate
|
||||
FEDORA_OPENSSL_SYS_DEPS="perl-FindBin perl-File-Compare perl-IPC-Cmd perl-File-Copy"
|
||||
|
||||
# FFmpeg dependencies
|
||||
FEDORA_FFMPEG_DEPS="libheif-devel ffmpeg ffmpeg-devel"
|
||||
|
||||
# Webkit2gtk requires gstreamer plugins for video playback to work
|
||||
FEDORA_VIDEO_DEPS="gstreamer1-devel gstreamer1-plugins-base-devel gstreamer1-plugins-good gstreamer1-plugins-good-gtk gstreamer1-plugins-good-extras gstreamer1-plugins-ugly-free gstreamer1-plugins-bad-free gstreamer1-plugins-bad-free-devel gstreamer1-plugins-bad-free-extras"
|
||||
|
||||
# Bindgen dependencies - it's used by a dependency of Spacedrive
|
||||
FEDORA_BINDGEN_DEPS="clang clang-devel"
|
||||
|
||||
# Protobuf compiler
|
||||
FEDORA_LIBP2P_DEPS="protobuf-compiler"
|
||||
|
||||
if ! sudo dnf install $FEDORA_37_TAURI_WEBKIT && ! sudo dnf install $FEDORA_36_TAURI_WEBKIT; then
|
||||
err 'We were unable to install the webkit2gtk4.0-devel/webkit2gtk3-devel package.' \
|
||||
'Please open an issue if you feel that this is incorrect.' \
|
||||
'https://github.com/spacedriveapp/spacedrive/issues'
|
||||
fi
|
||||
|
||||
if ! sudo dnf install $FEDORA_FFMPEG_DEPS; then
|
||||
err 'We were unable to install the FFmpeg and FFmpeg-devel packages.' \
|
||||
'This is likely because the RPM Fusion free repository is not enabled.' \
|
||||
'https://docs.fedoraproject.org/en-US/quick-docs/setup_rpmfusion'
|
||||
fi
|
||||
|
||||
sudo dnf group install "C Development Tools and Libraries"
|
||||
sudo dnf install $FEDORA_TAURI_DEPS $FEDORA_BINDGEN_DEPS $FEDORA_LIBP2P_DEPS $FEDORA_VIDEO_DEPS
|
||||
else
|
||||
err "Your Linux distro '$(lsb_release -s -d)' is not supported by this script." \
|
||||
'We would welcome a PR or some help adding your OS to this script:' \
|
||||
'https://github.com/spacedriveapp/spacedrive/issues'
|
||||
fi
|
||||
elif [ "$SYSNAME" = "Darwin" ]; then
|
||||
# Location for installing script dependencies
|
||||
_deps_dir="${_script_path}/deps"
|
||||
mkdir -p "$_deps_dir"
|
||||
PATH="${_deps_dir}:$PATH"
|
||||
export PATH
|
||||
|
||||
_arch="$(uname -m)"
|
||||
|
||||
# Symlink original macOS utils to avoid problems on system where the user has installed GNU utils
|
||||
ln -fs "/usr/bin/tar" "${_deps_dir}/tar"
|
||||
|
||||
if ! has jq; then
|
||||
echo "Download jq build..."
|
||||
|
||||
# Determine the machine's architecture
|
||||
case "$_arch" in
|
||||
x86_64)
|
||||
_jq_url='https://packages.macports.org/jq/jq-1.6_4.darwin_19.x86_64.tbz2'
|
||||
_oniguruma6_url='https://packages.macports.org/oniguruma6/oniguruma6-6.9.8_0.darwin_19.x86_64.tbz2'
|
||||
;;
|
||||
arm64)
|
||||
_jq_url='https://packages.macports.org/jq/jq-1.6_4.darwin_20.arm64.tbz2'
|
||||
_oniguruma6_url='https://packages.macports.org/oniguruma6/oniguruma6-6.9.8_0.darwin_20.arm64.tbz2'
|
||||
;;
|
||||
*)
|
||||
err "Unsupported architecture: $_arch"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Download the latest jq binary and deps from macports
|
||||
curl -LSs "$_jq_url" | tar -xjOf - ./opt/local/bin/jq >"${_deps_dir}/jq"
|
||||
curl -LSs "$_oniguruma6_url" | tar -xjOf - ./opt/local/lib/libonig.5.dylib >"${_deps_dir}/libonig.5.dylib"
|
||||
|
||||
# Make the binaries executable
|
||||
chmod +x "$_deps_dir"/*
|
||||
|
||||
# Make jq look for deps in the same directory
|
||||
install_name_tool -change '/opt/local/lib/libonig.5.dylib' '@executable_path/libonig.5.dylib' "${_deps_dir}/jq"
|
||||
fi
|
||||
|
||||
# Create frameworks directory to put Spacedrive dependencies
|
||||
_frameworks_dir="${_script_path}/../../target/Frameworks"
|
||||
rm -rf "$_frameworks_dir"
|
||||
mkdir -p "${_frameworks_dir}/"{bin,lib,include}
|
||||
_frameworks_dir="$(CDPATH='' cd -- "$_frameworks_dir" && pwd -P)"
|
||||
|
||||
exec 3>&1 # Copy stdout to fd 3.
|
||||
echo "Download ffmpeg build..."
|
||||
_page=1
|
||||
while [ $_page -gt 0 ]; do
|
||||
_success=$(gh_curl "${_gh_url}/${_sd_gh_path}/actions/workflows/ffmpeg-macos.yml/runs?page=${_page}&per_page=100&status=success" \
|
||||
| jq -r '. as $raw | .workflow_runs | if length == 0 then error("Error: \($raw)") else .[] | select(.head_branch == "main") | .artifacts_url end' \
|
||||
| while IFS= read -r _artifacts_url; do
|
||||
if _artifact_path="$(
|
||||
gh_curl "$_artifacts_url" \
|
||||
| jq --arg version "$FFMPEG_VERSION" --arg arch "$(
|
||||
if [ "${TARGET:-}" = 'aarch64-apple-darwin' ]; then
|
||||
echo 'arm64'
|
||||
else
|
||||
echo "$_arch"
|
||||
fi
|
||||
)" -r \
|
||||
'. as $raw | .artifacts | if length == 0 then error("Error: \($raw)") else .[] | select(.name == "ffmpeg-\($version)-\($arch)") | "suites/\(.workflow_run.id)/artifacts/\(.id)" end'
|
||||
)"; then
|
||||
if {
|
||||
gh_curl "${_gh_url}/${_sd_gh_path}/actions/artifacts/$(echo "$_artifact_path" | awk -F/ '{print $4}')/zip" \
|
||||
| tar -xOf- | tar -xJf- -C "$_frameworks_dir"
|
||||
} 2>/dev/null; then
|
||||
printf 'yes'
|
||||
exit
|
||||
else
|
||||
# nightly.link is a workaround for the lack of a public GitHub API to download artifacts from a workflow run
|
||||
# https://github.com/actions/upload-artifact/issues/51
|
||||
# Use it when running in evironments that are not authenticated with github
|
||||
if curl -LSs "https://nightly.link/${_sd_gh_path}/${_artifact_path}" | tar -xOf- | tar -xJf- -C "$_frameworks_dir"; then
|
||||
printf 'yes'
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Failed to ffmpeg artifiact release, trying again in 1sec..." >&3
|
||||
sleep 1
|
||||
fi
|
||||
done)
|
||||
|
||||
if [ "${_success:-}" = 'yes' ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
_page=$((_page + 1))
|
||||
|
||||
echo "ffmpeg artifact not found, trying again in 1sec..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Sign and Symlink the FFMpeg.framework libs to the lib directory
|
||||
for _lib in "${_frameworks_dir}/FFMpeg.framework/Libraries/"*; do
|
||||
if [ -f "$_lib" ]; then
|
||||
# Sign the lib with the local machine certificate (Required for it to work on macOS 13+)
|
||||
if ! codesign -s "${APPLE_SIGNING_IDENTITY:--}" -f "$_lib" 1>/dev/null 2>&1; then
|
||||
err "Failed to sign: ${_lib#"$_frameworks_dir"}" \
|
||||
'Please open an issue on https://github.com/spacedriveapp/spacedrive/issues'
|
||||
fi
|
||||
fi
|
||||
_lib="${_lib#"${_frameworks_dir}/FFMpeg.framework/Libraries/"}"
|
||||
ln -s "../FFMpeg.framework/Libraries/${_lib}" "${_frameworks_dir}/lib/${_lib}"
|
||||
done
|
||||
|
||||
# Symlink the FFMpeg.framework headers to the include directory
|
||||
for _header in "${_frameworks_dir}/FFMpeg.framework/Headers/"*; do
|
||||
_header="${_header#"${_frameworks_dir}/FFMpeg.framework/Headers/"}"
|
||||
ln -s "../FFMpeg.framework/Headers/${_header}" "${_frameworks_dir}/include/${_header}"
|
||||
done
|
||||
|
||||
# Workaround while https://github.com/tauri-apps/tauri/pull/3934 is not merged
|
||||
echo "Download patched tauri cli.js build..."
|
||||
(
|
||||
case "$_arch" in
|
||||
x86_64)
|
||||
_artifact_id="866514594"
|
||||
;;
|
||||
arm64)
|
||||
_artifact_id="866514593"
|
||||
;;
|
||||
*)
|
||||
err "Unsupported architecture: $_arch"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! {
|
||||
gh_curl "${_gh_url}/${_sd_gh_path}/actions/artifacts/${_artifact_id}/zip" \
|
||||
| tar -xf- -C "${_frameworks_dir}/bin"
|
||||
} 2>/dev/null; then
|
||||
# nightly.link is a workaround for the lack of a public GitHub API to download artifacts from a workflow run
|
||||
# https://github.com/actions/upload-artifact/issues/51
|
||||
# Use it when running in evironments that are not authenticated with github
|
||||
curl -LSs "https://nightly.link/${_sd_gh_path}/actions/artifacts/${_artifact_id}.zip" \
|
||||
| tar -xf- -C "${_frameworks_dir}/bin"
|
||||
fi
|
||||
)
|
||||
|
||||
echo "Download protobuf build"
|
||||
_page=1
|
||||
while [ $_page -gt 0 ]; do
|
||||
_success=$(gh_curl "${_gh_url}/protocolbuffers/protobuf/releases?page=${_page}&per_page=100" \
|
||||
| jq --arg arch "$(
|
||||
if [ "$_arch" = 'arm64' ]; then
|
||||
echo 'aarch_64'
|
||||
else
|
||||
echo 'x86_64'
|
||||
fi
|
||||
)" -r \
|
||||
'. as $raw | if length == 0 then error("Error: \($raw)") else .[] | select(.prerelease | not) | .assets[] | select(.name | endswith("osx-\($arch).zip")) | .browser_download_url end' \
|
||||
| while IFS= read -r _asset_url; do
|
||||
if curl -LSs "${_asset_url}" | tar -xf - -C "$_frameworks_dir"; then
|
||||
printf 'yes'
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "Failed to download protobuf release, trying again in 1sec..." >&3
|
||||
sleep 1
|
||||
done)
|
||||
|
||||
if [ "${_success:-}" = 'yes' ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
_page=$((_page + 1))
|
||||
|
||||
echo "protobuf release not found, trying again in 1sec..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Ensure all binaries are executable
|
||||
chmod +x "$_frameworks_dir"/bin/*
|
||||
|
||||
cat <<EOF >"${_cargo_config}/config"
|
||||
[env]
|
||||
PROTOC = "${_frameworks_dir}/bin/protoc"
|
||||
FFMPEG_DIR = "${_frameworks_dir}"
|
||||
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = ["-L", "${_frameworks_dir}/lib"]
|
||||
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = ["-L", "${_frameworks_dir}/lib"]
|
||||
|
||||
$(cat "${_cargo_config}/config.toml")
|
||||
EOF
|
||||
else
|
||||
err "Your OS ($SYSNAME) is not supported by this script." \
|
||||
'We would welcome a PR or some help adding your OS to this script.' \
|
||||
'https://github.com/spacedriveapp/spacedrive/issues'
|
||||
fi
|
||||
|
||||
echo "Your machine has been successfully set up for Spacedrive development."
|
||||
Reference in New Issue
Block a user