bionicles

Abstract Idempotent Provision of Requirements with PowerShell, or "doing microsoft's job for them"

Jun 12th, 2023
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 8.69 KB | Software | 0 0
  1. # C:\Users\[user]\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
  2. # Abstract Idempotent Provision of Requirements with PowerShell, or
  3. # "doing microsoft's job for them"
  4. $SCOOP_REQUIREMENTS = @(
  5.     "make",
  6.     "rust",
  7.     "rustup",
  8.     "gh",
  9.     "nodejs",
  10.     "go",
  11.     "fzf"
  12. )
  13. $REQUIREMENTS = @(
  14.     "scoop",
  15.     "make",
  16.     "gh",
  17.     "conda",
  18.     "python",
  19.     "node",
  20.     "cargo",
  21.     "rustup"
  22.     "rg",
  23.     "grep",
  24.     "go",
  25.     "fzf"
  26. )
  27.  
  28. function Log($message) {
  29.     $timestamp = Get-Date -Format o
  30.     Write-Host "[$timestamp] $message"
  31. }
  32. Log "Initiate Idempotent Requirement Provision"
  33.  
  34. # Alias "cp" to cat all the profiles
  35. function Show-Profiles {
  36.     $profilePaths = $PROFILE.PSObject.Properties.Value
  37.     $profilePaths | ForEach-Object {
  38.         if (Test-Path $_) {
  39.             Write-Host "`n`n=== Contents of $_ ===`n`n"
  40.             Get-Content $_
  41.         }
  42.     }
  43. }
  44. Set-Alias -Name catp -Value Show-Profiles
  45. Log "Initial Profiles:"
  46. Show-Profiles
  47.  
  48. # Alias "pp" to print $PATH
  49. function Show-Path {
  50.     $env:Path -split ';'
  51. }
  52. Set-Alias -Name pp -Value Show-Path
  53. Log "Initial $env.Path:"
  54. Show-Path
  55.  
  56.  
  57. function Show-Error($err) {
  58.     Log "ERROR!: $($err.Exception.Message)"
  59.     Log "Continue provision..."
  60. }
  61.  
  62. function Get-ScoopPackagePath {
  63.     param(
  64.         [Parameter(Mandatory = $true)]
  65.         [string]$PackageName
  66.     )
  67.     Log "Get-ScoopPackagePath PackageName $PackageName"
  68.     $result = scoop prefix $PackageName
  69.     Log "Get-ScoopPackagePath PackageName = $PackageName result = $result"
  70.     return $result
  71. }
  72.  
  73. function Check-Command {
  74.     param(
  75.         [Parameter(Mandatory = $true)]
  76.         [string]$Name
  77.     )
  78.     try {
  79.         $command = Get-Command $Name -ErrorAction SilentlyContinue
  80.         if ($null -eq $command) {
  81.             Log "Get-Command Failed on $Name. Falling back to Get-ScoopPackagePath"
  82.             return Get-ScoopPackagePath  -PackageName $Name
  83.         }
  84.         else {
  85.             Log "Command '$Name' is found at $($command.Source)."
  86.             return $command.Source
  87.         }
  88.     }
  89.     catch {
  90.         Log "Command '$Name' is not found."
  91.     }
  92. }
  93.  
  94. function Add-ToPath {
  95.     param(
  96.         [Parameter(Mandatory = $true)]
  97.         [string]$PathToAdd
  98.     )
  99.     $paths = $env:Path -split ';'
  100.     if ($paths -notcontains $PathToAdd) {
  101.         Log "Add-ToPath PathToAdd = $PathToAdd"
  102.         $paths += $PathToAdd
  103.         $env:Path = $paths -join ';'
  104.     }
  105. }
  106.  
  107. function Install-Scoop {
  108.     if (!(Test-Path "C:\ProgramData\scoop")) {
  109.         try {
  110.             Log "Installing Scoop"
  111.             Invoke-Expression "& {$(Invoke-RestMethod get.scoop.sh)} -RunAsAdmin"
  112.             Log "Scoop installed"
  113.         }
  114.         catch {
  115.             Log "Install-Scoop did not install scoop."
  116.         }
  117.     }
  118.     Add-ToPath -PathToAdd "C:\Users\$env:USERNAME\scoop\shims"
  119.     scoop bucket add extras
  120. }
  121. Install-Scoop
  122.  
  123.  
  124.  
  125. function Scoop-Install {
  126.     param(
  127.         [Parameter(Mandatory = $true)]
  128.         [string]$Name,
  129.         [string]$PathToAdd
  130.     )
  131.     Log "Scoop-Install $Name"
  132.     $commandPath = Check-Command $Name
  133.     try {
  134.         if ($null -eq $commandPath) {
  135.             Log "Installing $Name with scoop"
  136.             scoop install $Name
  137.             Log "$Name Installed with scoop"
  138.         }
  139.         else {
  140.             Log "$Name is already installed at $commandPath."
  141.         }
  142.     }
  143.     catch {
  144.         Log "caught error in scoop install Name = $Name & PathToAdd = $PathToAdd"
  145.         Show-Error $_
  146.     }
  147.     Log "Update $Name"
  148.     try {
  149.         scoop update $Name
  150.     }
  151.     catch {
  152.         Log "caught error in scoop upgrade Name = $Name & PathToAdd = $PathToAdd"
  153.         Show-Error $_
  154.     }
  155.     Log "Finished Scoop-Install $Name."
  156. }
  157. foreach ($requirement in $SCOOP_REQUIREMENTS) {
  158.     Log "provision scoop requirement $requirement"
  159.     try {
  160.         Scoop-Install -Name $requirement
  161.     }
  162.     catch {
  163.         Log "Caught an issue on $requirement"
  164.     }
  165. }
  166.  
  167.  
  168.  
  169. # FUNCTION to install and activate conda environment
  170. function Start-CondaEnv {
  171.     $minicondaInstallPath = "C:\Miniconda3"
  172.     $condaEnvName = "py310"
  173.     $condaEnvPythonVersion = 3.10
  174.     Log "Check Conda Installed"
  175.     if (!(Test-Path $minicondaInstallPath)) {
  176.         Log "conda missing from $minicondaInstallPath"
  177.         Log "Download Miniconda Installer"
  178.         $minicondaInstaller = "https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe"
  179.         Invoke-WebRequest -Uri $minicondaInstaller -OutFile "$HOME\Downloads\Miniconda3-latest-Windows-x86_64.exe"
  180.         Log "Miniconda Installer Downloaded"
  181.         Log "Install Miniconda"
  182.         Start-Process -FilePath "$HOME\Downloads\Miniconda3-latest-Windows-x86_64.exe" -ArgumentList "/S /InstallationType=JustMe /AddToPath=1 /D=$minicondaInstallPath" -Wait
  183.     }
  184.     Log "Conda Installed"
  185.     Log "Update Conda"
  186.     conda update -n base -c defaults conda -y
  187.     Log "Conda Updated"
  188.     Log "Add conda to PATH"
  189.     Add-ToPath -PathToAdd "$minicondaInstallPath\Scripts"
  190.     Log "conda added to path"
  191.     Log "check conda env exists"
  192.     if (!(Test-Path -Path "C:\Miniconda3\envs\$condaEnvName")) {
  193.         Log "Create Conda Env"
  194.         conda create -n $condaEnvName python=$condaEnvPythonVersion -y
  195.     }
  196.     Log "initialize conda"
  197.     conda init powershell
  198.     Log "conda initialized"
  199.     Log "activate conda env $condaEnvName"
  200.     conda activate $condaEnvName
  201.     Log "conda env $condaEnvName activated"
  202.     # Alias Python
  203.     Log "Alias Python"
  204.     Set-Alias -Name python -Value "C:\Miniconda3\envs\py310\python.exe"
  205.     Log "Python Aliased"
  206.     # Update pip
  207.     Log "Upgrade Pip"
  208.     python -m pip install --upgrade pip
  209.     Log "Pip Upgraded"
  210.     Log "Done Provisioning Conda & Python Env"
  211. }
  212. Start-CondaEnv
  213.  
  214. # When installing build tools, these two components should be selected:
  215. # - MSVC - VS C++ x64/x86 build tools
  216. # - Windows SDK
  217. $MSVCPATH = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC'
  218. function Install-VSBuildTools {
  219.     $vs_buildtools_uri = "https://aka.ms/vs/17/release/vs_buildtools.exe"
  220.     $vs_buildtools_exe = "$env:TEMP\vs_buildtools.exe"
  221.     $vs_buildtools_args = "--quiet --wait --norestart --nocache "
  222.     $vs_buildtools_args += "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 "
  223.     $vs_buildtools_args += "--add Microsoft.VisualStudio.Component.Windows10SDK.18362 "
  224.  
  225.     if (!(Test-Path $MSVCPATH)) {
  226.         Log "Downloading Visual Studio 2019 Build Tools..."
  227.         Invoke-WebRequest -Uri $vs_buildtools_uri -OutFile $vs_buildtools_exe
  228.         Log "Installing Visual Studio 2019 Build Tools..."
  229.         Start-Process -FilePath $vs_buildtools_exe -ArgumentList $vs_buildtools_args -Wait
  230.         Log "Visual Studio 2019 Build Tools installed"
  231.     }
  232.     else {
  233.         Log "Visual Studio 2019 Build Tools already installed"
  234.     }
  235. }
  236. Install-VSBuildTools
  237. $versionDirectories = Get-ChildItem -Path $MSVCPATH -Directory
  238. Log "versionDirectories $versionDirectories"
  239. # Convert the directory names to version numbers and sort them in descending order.
  240. $versions = $versionDirectories.Name | ForEach-Object { [version] $_ } | Sort-Object -Descending
  241. Log "versions $versions"
  242. # The highest version is the first one in the sorted list.
  243. $highestVersion = $versions[0]
  244. Log "highestVersion $highestVersion"
  245. # The path to the highest version of the build tools is then:
  246. $highestMsvcVersionPath = Join-Path -Path $MSVCPATH -ChildPath $highestVersion.ToString()
  247. Log "Highest MSVC Version Path is $highestMsvcVersionPath"
  248.  
  249.  
  250. function Install-Crates {
  251.     Log "install ripgrep"
  252.     cargo install ripgrep
  253.     Add-ToPath -PathToAdd "C:\Users\$env:USERNAME\.cargo\bin"
  254.     Log "ripgrep installed"
  255. }
  256. Install-Crates
  257. Log "alias grep to rg"
  258. $RIPGREP_PATH = "C:\Users\$env:USERNAME\.cargo\bin\rg.exe"
  259. Set-Alias -Name grep -Value $RIPGREP_PATH
  260.  
  261. Log "env.Path is now $env:Path"
  262. Log "End Abstract Idempotent Provision of Requirements"
  263. Log "Final Status Report:"
  264. function Show-Requirements {
  265.     $StatusReport = @{}
  266.     function Measure-Status {
  267.         param(
  268.             [Parameter(Mandatory = $true)]
  269.             [string]$Name          
  270.         )
  271.         $requirementPath = Check-Command $Name
  272.         if ($null -eq $requirementPath) {
  273.             $StatusReport[$Name] = 'Not Ready'
  274.         }
  275.         else {
  276.             if ($Name -eq "grep") {
  277.                 $requirementPath = $RIPGREP_PATH
  278.             }  
  279.             $StatusReport[$Name] = @{
  280.                 'Status' = 'Ready'
  281.                 'Path'   = $requirementPath
  282.             }
  283.         }
  284.     }
  285.     foreach ($app in $REQUIREMENTS) {
  286.         Measure-Status -Name $app
  287.     }
  288.     if ($null -eq $highestMsvcVersionPath) {
  289.         $StatusReport["C++ x64/x86 build tools"] = @{'Status'='Not Ready'}
  290.     }
  291.     else {
  292.         $StatusReport["C++ x64/x86 build tools"] = @{
  293.             'Status' = 'Ready'
  294.             'Path' = $highestMsvcVersionPath
  295.         }
  296.     }
  297.     $StatusReport.GetEnumerator() | Sort-Object Name | Format-Table -Property Name, @{
  298.         Name = 'Status'; Expression = { $_.Value.Status }
  299.     }, @{
  300.         Name = 'Path'; Expression = { $_.Value.Path }
  301.     } -AutoSize
  302. }
  303. Show-Requirements
  304.  
  305. # Alias to locate $PROFILE
  306. function Find-Profile {
  307.     $PROFILE | Format-List *
  308. }
  309. Set-Alias -Name lp -Value Find-Profile
  310. # Alias "eb" to edit $PROFILE
  311. function Edit-Profile {
  312.     code $PROFILE
  313.     code -a "$($env:USERPROFILE)\Documents\PowerShell"
  314. }
  315. Set-Alias -Name eb -Value Edit-Profile
  316. # Alias "sb" to source $PROFILE
  317. function Set-Profile {
  318.     . $PROFILE
  319. }
  320. Set-Alias -Name sb -Value Set-Profile
  321. # Alias "cb" to cat $PROFILE
  322. function Show-Profile {
  323.     Get-Content $PROFILE
  324. }
  325. Set-Alias -Name cb -Value Show-Profile
Advertisement
Add Comment
Please, Sign In to add comment