Last active
August 28, 2024 00:46
-
-
Save techthoughts2/3b3f44ddbac0cc8f8331b7d97c2162f8 to your computer and use it in GitHub Desktop.
This PowerShell script will setup a fresh workstation with everything needed to sucessfully work and be a DevOps Master day-to-day.
This file contains 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
#region installs | |
# core tech choco installs | |
$script:chocoCoreTech = @( | |
# 'vscode' # visual studio code | |
# 'python' # python | |
# '7zip' # file archiver with good compression ratio | |
# 'git' # git for windows | |
# 'firefox' # firefox browser | |
) | |
# core tech winget installs | |
$script:wingetCoreTech = @( | |
'Git.Git' # git for windows | |
'Microsoft.VisualStudioCode' # visual studio code | |
'Python.Python.3' #python | |
'7zip.7zip' # file archiver with good compression ratio | |
'Mozilla.Firefox' # firefox browser | |
'JanDeDobbeleer.OhMyPosh' # oh my posh | |
'Microsoft.PowerShell' # powershell | |
) | |
# basic choco installs | |
$script:chocoSoftwareInstalls = @( | |
# 'ytmdesktop' #https://github.com/ytmdesktop/ytmdesktop/issues/563 | |
# 'spotify' # spotify | |
# 'cacher' # code snippet organizer | |
# 'winscp' # Open source free SFTP client, SCP client, FTPS client and FTP client | |
# 'telegram' # Cloud-based synchronized messaging app with a focus on speed and security | |
# 'grepwin' # powerful and fast search tool using regular expressions. | |
# 'notepadplusplus' # source code editor and Notepad replacement | |
# 'googlechrome' # chrome browser | |
# 'foxitreader' # pdf client | |
'paint.net' # photo editor | |
) | |
# basic winget installs | |
$script:wingetSoftwareInstalls = @( | |
'Spotify.Spotify' # spotify | |
'PenguinLabs.Cacher' # code snippet organizer | |
'WinSCP.WinSCP' # Open source free SFTP client, SCP client, FTPS client and FTP client | |
'Telegram.TelegramDesktop' # Cloud-based synchronized messaging app with a focus on speed and security | |
'StefansTools.grepWin' # powerful and fast search tool using regular expressions. | |
'Notepad++.Notepad++' # source code editor and Notepad replacement | |
# 'Google.Chrome' # chrome browser | |
# 'Foxit.FoxitReader' # pdf client | |
'JGraph.Draw' # draw.io | |
'WinDirStat.WinDirStat' # disk usage analyzer | |
'NickeManarin.ScreenToGif' # screen recorder to gif | |
'DominikReichl.KeePass' #KeePass | |
) | |
# choco azure installs | |
$script:chocoInstallsAzure = @( | |
# 'azure-cli' # cli for azure | |
# 'AzureStorageExplorer' # the azure storage explorer | |
# 'azure-functions-core-tools-3' # core tool set for local dev of azure functions | |
'azcopy10' # azure copy tool | |
# 'bicep' # bicep cli | |
) | |
# winget azure installs | |
$script:wingetInstallsAzure = @( | |
'Microsoft.AzureCLI' # cli for azure | |
'Microsoft.AzureStorageExplorer' # the azure storage explorer | |
'Microsoft.AzureFunctionsCoreTools' # core tool set for local dev of azure functions | |
'Microsoft.AzureStorageEmulator' | |
'Microsoft.Bicep' # bicep cli | |
) | |
# choco aws installs | |
$script:chocoInstallsAWS = @( | |
'aws-vault' # A tool to securely store and access AWS credentials in a development environment | |
# 'awscli' # aws cli | |
) | |
# winget aws installs | |
$script:wingetInstallsAWS = @( | |
'Amazon.AWSCLI' # aws cli | |
'Amazon.SAM-CLI' # aws sam cli | |
'Amazon.SessionManagerPlugin' # aws session manager plugin | |
) | |
# winget aws cdk typescript installs | |
$script:wingetAWSCDKTypeScript = @( | |
'Amazon.AWSCLI' # aws cli | |
'OpenJS.NodeJS' # nodejs | |
) | |
# a list of useful Azure PowerShell modules | |
$script:azureModules = @( | |
'Az' # standard Azure modules | |
'AzureDevOps' # interact with the Azure DevOps REST API. | |
'AzurePipelinesPS' # makes interfacing with Azure Pipelines a bit easier. | |
'CosmosDB' # provides cmdlets for working with Azure Cosmos DB. | |
'PSArm' # experimental DSL for ARM templates (based on bicep) | |
'Bicep' # enable the features provided by the Bicep CLI in PowerShell. | |
) | |
# a list of useful AWS PowerShell modules | |
$script:awsModules = @( | |
'AWS.Tools.Common' | |
'AWS.Tools.CloudWatch' | |
'AWS.Tools.CostExplorer' | |
'AWS.Tools.S3' | |
'AWS.Tools.SecretsManager' | |
'AWS.Tools.SecurityToken' | |
'AWS.Tools.SQS' | |
) | |
# a list of useful Core PowerShell modules | |
$script:modules = @( | |
@{ | |
ModuleName = 'Catesta' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'Convert' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'DnsClient-PS' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'InvokeBuild' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'Pester' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'platyPS' | |
Version = '0.12.0' | |
} | |
@{ | |
ModuleName = 'posh-git' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'PoshGram' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'PSReadline' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'PSScriptAnalyzer' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'PSWordCloud' | |
Version = 'Latest' | |
} | |
@{ | |
ModuleName = 'Terminal-Icons' | |
Version = 'Latest' | |
} | |
) | |
# python VSCode extensions | |
$script:vscodeExtensionsPython = @( | |
'almenon.arepl' #AREPL automatically evaluates python code in real-time as you type. | |
'formulahendry.code-runner' #Run code snippet or code file for multiple languages: | |
'ms-python.python' #python | |
'ms-python.vscode-pylance' #Fast, feature-rich language support for Python | |
'ms-toolsai.jupyter' #basic notebook support for language kernels | |
'njpwerner.autodocstring' #quickly generate docstrings for python functions. | |
) | |
# aws VSCode extensions | |
$script:vscodeExtensionsAWS = @( | |
'amazonwebservices.aws-toolkit-vscode' #AWS Toolkit is an extension for Visual Studio Code that enables you to interact with Amazon Web Services (AWS). | |
'aws-scripting-guy.cform' #CloudFormation support | |
'DanielThielking.aws-cloudformation-yaml' #This extension adds some snippets to YAML based files for AWS CloudFormation. | |
'kddejong.vscode-cfn-lint' #VS Code CloudFormation Linter uses cfn-lint to lint your CloudFormation templates. | |
) | |
# aws cdktf VSCode extensions | |
$script:vscodeExtensionsAWSCDK = @( | |
'dbaeumer.vscode-eslint' #Integrates ESLint JavaScript into VS Code. | |
) | |
# azure VSCode extensions | |
$script:vscodeExtensionsAzure = @( | |
'damienaicheh.azure-devops-snippets' #Azure DevOps snippets | |
'ms-dotnettools.vscode-dotnet-runtime' #.NET Install Tool for Extension Authors - dependency | |
'ms-azure-devops.azure-pipelines' #Syntax highlighting, IntelliSense, and more for Azure Pipelines YAML | |
'ms-azuretools.vscode-azureresourcegroups' #View and manage Azure resources directly from VS Code. | |
'ms-azuretools.vscode-azurefunctions' #Use the Azure Functions extension to quickly create, debug, manage, and deploy serverless apps directly from VS Code. | |
'msazurermtools.azurerm-vscode-tools' #The Azure Resource Manager (ARM) Tools for Visual Studio Code | |
'ms-azuretools.vscode-bicep' #Bicep language support | |
'ms-vscode.azure-account' #The Azure Account extension provides a single Azure sign-in | |
'ms-vscode.azurecli' #Scrapbooks for developing and running commands with the Azure CLI. | |
) | |
# core VSCode extensions | |
$script:vscodeExtensions = @( | |
'aaron-bond.better-comments' #The Better Comments extension will help you create more human-friendly comments in your code. | |
'alexey-strakh.stackoverflow-search' #search stackoverflow direct from vscode | |
'DavidAnson.vscode-markdownlint' #Markdown/CommonMark linting and style checking | |
'DotJoshJohnson.xml' #xml tools | |
'eamodio.gitlens' #GitLens supercharges the Git capabilities | |
'emilast.LogFileHighlighter' #Adds color highlighting to log files | |
# 'GitHub.copilot' #AI pair programmer from GitHub | |
'hediet.vscode-drawio' #This unofficial extension integrates Draw.io | |
'mechatroner.rainbow-csv' #Highlight columns in comma (.csv), tab (.tsv), semicolon and pipe | |
# 'ms-dotnettools.csharp' #Welcome to the C# extension for Visual Studio Code! | |
'ms-vscode.powershell' #PowerShell! | |
'nobuhito.printcode' #adds print to VSCode | |
'oderwat.indent-rainbow' #make indentation more readable | |
'PKief.material-icon-theme' #material icon theme for icons | |
'redhat.vscode-yaml' #Provides comprehensive YAML Language support - dependency | |
'ritwickdey.LiveServer' #go live | |
'ryanluker.vscode-coverage-gutters' #codecoverage indicator | |
'ryu1kn.partial-diff' #You can compare (diff) text selections within a file, across different files, or to the clipboard | |
'shd101wyy.markdown-preview-enhanced' #Markdown Preview Enhanced | |
'SirTori.indenticator' #Visually highlights the current indent depth. | |
'streetsidesoftware.code-spell-checker' #A basic spell checker that works well with camelCase code. | |
'tuxtina.json2yaml' #Uses js-yaml to do the actual conversion json to yaml and vice-versa. | |
'Tyriar.shell-launcher' #Easily launch multiple shell configurations in the terminal. | |
'usernamehw.errorlens' #ErrorLens turbo-charges language diagnostic features by making diagnostics stand out more prominently | |
'vangware.dark-plus-material' #theme | |
'vincentkos.snippet-creator' #helps to automate snippet creation | |
'wmontalvo.vsc-jsonsnippets' #Makes writing key-value code (like JSON) fluent, with a simple set of snippets | |
'yzhang.markdown-all-in-one' #All you need for Markdown | |
) | |
#endregion | |
#region paths | |
$script:tempPath = -join ($env:TEMP, '\ws_setup') | |
$script:vscodeSettingsPath = -join ($env:APPDATA, '\Code\User') | |
$script:vscodeSnippetsPath = -join ($env:APPDATA, '\Code\User\snippets') | |
$script:windowsTerminalSettingsPath = -join ($env:LOCALAPPDATA, '\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState') | |
$script:windowsTerminalBackgroundPath = -join ($env:LOCALAPPDATA, '\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\RoamingState') | |
# $script:profilePath = -join ($env:USERPROFILE, '\Documents\PowerShell') | |
# $script:profilePath = $profile.CurrentUserAllHosts | |
$script:ohmyposhSettings = $env:USERPROFILE | |
#endregion | |
#region content locations | |
$gistUrl = "https://api.github.com/gists/a208d2bd924691bae7ec7904cab0bd8e" | |
$script:psProfile = 'https://api.github.com/gists/2b4d8e590a7fa41f32a76013df664020' | |
$script:vsCodeSettingsJSON = 'https://api.github.com/gists/d0997337224510743e2072dc5c343363' #settings.json | |
$script:vsCodePythonSnippetsJSON = 'https://api.github.com/gists/042b2b47e7a94c1a5a2bc79439a4fb81' #vscode_python_snippets.json | |
$script:vsCodePowerShellSnippetsJSON = 'https://api.github.com/gists/9ec91ab0ca26f96cf7ca4842053fa8fb' #vscode_ps_snippets.json | |
$script:windowsTerminalSettingsJSON = 'https://api.github.com/gists/df416a8df55c6c4009c9dcd337d4c8cf' #settings.json | |
$script:ohmyposhJSON = 'https://api.github.com/gists/da99b8255a8ca720430d188f649a9bd7' #.jake.omp.json | |
$script:setupFiles = 'https://tt-ws.s3-us-west-2.amazonaws.com/ws.zip' #zip containing background images and fonts | |
#endregion | |
#region supporting functions | |
<# | |
.SYNOPSIS | |
Evaluates if chocolatey is installed | |
#> | |
function Test-Choco { | |
[CmdletBinding()] | |
param ( | |
) | |
$result = $true #assume the best | |
$testchoco = pwsh -noprofile -c 'choco -v' | |
if ($testchoco[0] -like "*.*.*" -and $testchoco[0] -notlike '*not*recognized*') { | |
Write-Verbose -Message "Chocolatey Version: $testchoco" | |
} | |
else { | |
Write-Verbose -Message "Chocolatey is not installed." | |
$result = $false | |
} | |
return $result | |
} #Test-Choco | |
<# | |
.SYNOPSIS | |
Evaluates if WinGet is installed | |
#> | |
function Test-WinGet { | |
[CmdletBinding()] | |
param ( | |
) | |
$result = $true #assume the best | |
$testwinget = pwsh -noprofile -c 'winget -v' | |
if ($testwinget[0] -like "v*") { | |
Write-Verbose -Message "winget Version: $testwinget" | |
} | |
else { | |
Write-Verbose -Message "winget is not installed." | |
$result = $false | |
} | |
return $result | |
} #Test-WinGet | |
<# | |
.SYNOPSIS | |
Installs chocolatey | |
#> | |
function Install-Choco { | |
[CmdletBinding()] | |
param ( | |
) | |
Write-Verbose -Message 'Installing Chocolately...' | |
Write-Verbose -Message 'Setting execution and security settings...' | |
Set-ExecutionPolicy Bypass -Scope Process -Force | |
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 | |
try { | |
Write-Verbose -Message 'Downloading and installing...' | |
Invoke-WebRequest https://chocolatey.org/install.ps1 -UseBasicParsing -ErrorAction Stop | Invoke-Expression -ErrorAction Stop | |
Write-Verbose -Message 'INSTALL COMPLETE.' | |
} | |
catch { | |
Write-Error $_ | |
} | |
} #InstallChoco | |
<# | |
.SYNOPSIS | |
Installs Azure related PowerShell modules | |
#> | |
function Install-HelpfulAzureModules { | |
[CmdletBinding()] | |
param ( | |
) | |
Write-Verbose -Message 'Evaluating Azure modules...' | |
foreach ($module in $script:azureModules) { | |
Write-Verbose -Message (' {0} evaluating...' -f $module) | |
if (-not (Get-Module $module -ListAvailable)) { | |
if ($module -eq 'PSArm') { | |
Write-Verbose -Message (' Installing {0}' -f $module) | |
Install-Module -Name $module -Scope CurrentUser -Repository PSGallery -AllowPrerelease -Force -AllowClobber | |
} | |
else { | |
Write-Verbose -Message (' Installing {0}' -f $module) | |
Install-Module -Name $module -Scope CurrentUser -Repository PSGallery -Force | |
} | |
} | |
else { | |
Write-Verbose -Message (' {0} VERIFIED. NO ACTION TAKEN.' -f $module) | |
} | |
} | |
} #Install-HelpfulAzureModules | |
<# | |
.SYNOPSIS | |
Installs Core PowerShell modules | |
#> | |
function Install-BaseModules { | |
[CmdletBinding()] | |
param ( | |
) | |
Write-Verbose -Message 'Evaluating modules...' | |
foreach ($module in $script:modules) { | |
Write-Verbose -Message (' {0} evaluating...' -f $module.ModuleName) | |
if ($module.Version -like "*beta*" -or $module.Version -like "*rc*") { | |
Write-Verbose -Message (' {0} version check...' -f $module.Version) | |
$moduleEval = Get-InstalledModule -Name $module.ModuleName -RequiredVersion $module.Version -AllowPrerelease -ErrorAction SilentlyContinue | |
} | |
elseif ($module.Version -ne 'Latest') { | |
Write-Verbose -Message (' {0} version check...' -f $module.Version) | |
$moduleEval = Get-InstalledModule -Name $module.ModuleName -RequiredVersion $module.Version -ErrorAction SilentlyContinue | |
} | |
else { | |
$moduleEval = Get-Module -Name $module.ModuleName -ListAvailable -ErrorAction SilentlyContinue | |
} | |
if (-not $moduleEval) { | |
if ($module.Version -like "*beta*" -or $module.Version -like "*rc*") { | |
Write-Verbose -Message (' Installing {0} - {1}' -f $module.ModuleName, $module.Version) | |
Install-Module -Name $module.ModuleName -Scope CurrentUser -Repository PSGallery -RequiredVersion $module.Version -Force -AllowPrerelease | |
} | |
elseif ($module.Version -ne 'Latest') { | |
Write-Verbose -Message (' Installing {0} - {1}' -f $module.ModuleName, $module.Version) | |
Install-Module -Name $module.ModuleName -Scope CurrentUser -Repository PSGallery -RequiredVersion $module.Version -Force | |
} | |
else { | |
Write-Verbose -Message (' Installing {0}' -f $module.ModuleName) | |
Install-Module -Name $module.ModuleName -Scope CurrentUser -Repository PSGallery -Force | |
} | |
} | |
else { | |
Write-Verbose -Message (' {0} VERIFIED. NO ACTION TAKEN.' -f $module.ModuleName) | |
} | |
} | |
} #Install-BaseModules | |
<# | |
.SYNOPSIS | |
Uninstalls older versions of Pester that ship with Windows | |
#> | |
function Uninstall-Pester ([switch]$All) { | |
if ([IntPtr]::Size * 8 -ne 64) { | |
throw "Run this script from 64bit PowerShell." | |
} | |
$pesterPaths = foreach ($programFiles in ($env:ProgramFiles, ${env:ProgramFiles(x86)})) { | |
$path = "$programFiles\WindowsPowerShell\Modules\Pester" | |
if ($null -ne $programFiles -and (Test-Path $path)) { | |
if ($All) { | |
Get-Item $path | |
} | |
else { | |
Get-ChildItem "$path\3.*" | |
} | |
} | |
} | |
if (-not $pesterPaths) { | |
"There are no Pester$(if (-not $all) {" 3"}) installations in Program Files and Program Files (x86) doing nothing." | |
return | |
} | |
foreach ($pesterPath in $pesterPaths) { | |
takeown /F $pesterPath /A /R | |
icacls $pesterPath /reset | |
# grant permissions to Administrators group, but use SID to do | |
# it because it is localized on non-us installations of Windows | |
icacls $pesterPath /grant "*S-1-5-32-544:F" /inheritance:d /T | |
Remove-Item -Path $pesterPath -Recurse -Force -Confirm:$false | |
} | |
} #Uninstall-Pester | |
<# | |
.SYNOPSIS | |
Installs VSCode extension | |
#> | |
function Install-VSCodeExtension { | |
[CmdletBinding()] | |
param ( | |
[string[]]$ExtensionList | |
) | |
foreach ($Extension in $ExtensionList) { | |
Write-Verbose -Message "Installing $Extension ..." | |
code --install-extension $Extension | |
} | |
} | |
<# | |
.SYNOPSIS | |
Evaluates if a package is installed with choco | |
#> | |
function Test-ChocoInstall { | |
[CmdletBinding()] | |
param ( | |
# choco package to be checked for | |
[Parameter(Mandatory = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$ChocoPackage | |
) | |
$result = $true #assume the best | |
$eval = $null | |
Write-Verbose -Message "Checking for $ChocoPackage..." | |
$eval = pwsh -noprofile -c "choco list --localonly $ChocoPackage" | |
if ($eval -match $ChocoPackage) { | |
Write-Verbose -Message 'Package VERIFIED.' | |
} | |
else { | |
Write-Verbose -Message 'Package NOT FOUND' | |
$result = $false | |
} | |
return $result | |
} #Test-ChocoInstall | |
<# | |
.SYNOPSIS | |
Install choco package | |
#> | |
function Install-ChocoPackage { | |
[CmdletBinding()] | |
param ( | |
# choco package to be installed | |
[Parameter(Mandatory = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$ChocoPackage | |
) | |
Write-Verbose -Message ('Choco installing - {0}' -f $ChocoPackage) | |
pwsh -noprofile -c "choco install $ChocoPackage -y" | |
} #Install-ChocoPackage | |
<# | |
.SYNOPSIS | |
Evaluates if a package is installed with choco | |
#> | |
function Test-WingetInstall { | |
[CmdletBinding()] | |
param ( | |
# winget package to be checked for | |
[Parameter(Mandatory = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$WingetPackage | |
) | |
$result = $true #assume the best | |
$eval = $null | |
Write-Verbose -Message "Checking for $WingetPackage..." | |
$eval = pwsh -noprofile -c "winget list --id=$WingetPackage --exact --accept-source-agreements" | |
if ($eval -like "*$WingetPackage*") { | |
Write-Verbose -Message 'Package VERIFIED.' | |
} | |
else { | |
Write-Verbose -Message 'Package NOT FOUND' | |
$result = $false | |
} | |
return $result | |
} #Test-WingetInstall | |
<# | |
.SYNOPSIS | |
Install winget package | |
#> | |
function Install-WingetPackage { | |
[CmdletBinding()] | |
param ( | |
# winget package to be installed | |
[Parameter(Mandatory = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$WingetPackage | |
) | |
Write-Verbose -Message ('winget installing - {0}' -f $WingetPackage) | |
pwsh -noprofile -c "winget install --id=$WingetPackage --silent --accept-package-agreements --accept-source-agreements" | |
} #Install-WingetPackage | |
<# | |
.SYNOPSIS | |
Evaluates if workstation setup files are present. If not downloads and unzips. | |
#> | |
function Get-WSSetupFiles { | |
[CmdletBinding()] | |
param ( | |
) | |
$wsFilesPath = -join ($script:tempPath, '\ws_files') | |
Write-Verbose -Message "Evaluating if $wsFilesPath is present..." | |
if (-not (Test-Path $wsFilesPath)) { | |
Write-Verbose -Message ' Downloading workstation setup files...' | |
try { | |
$invokeSplat = @{ | |
Uri = $script:setupFiles | |
OutFile = "$script:tempPath\ws.zip" | |
ErrorAction = 'Stop' | |
} | |
Invoke-WebRequest @invokeSplat | |
Write-Verbose -Message ' Download complete.' | |
} | |
catch { | |
Write-Error $_ | |
return | |
} | |
try { | |
Write-Verbose -Message ' Expanding zip download...' | |
$expandSplat = @{ | |
LiteralPath = "$script:tempPath\ws.zip" | |
DestinationPath = $wsFilesPath | |
ErrorAction = 'Stop' | |
} | |
Expand-Archive @expandSplat | |
Write-Verbose -Message ' UNZIPPED!' | |
} | |
catch { | |
Write-Error $_ | |
return | |
} | |
} | |
else { | |
Write-Verbose -Message " VERIFIED. No action taken." | |
} | |
} #Get-WSSetupFiles | |
<# | |
.SYNOPSIS | |
Retrieves settings files from github and places in appropriate locations | |
#> | |
function Set-SettingsFiles { | |
[CmdletBinding()] | |
param ( | |
) | |
$settings = @( | |
@{ | |
Name = 'VSCode Settings' | |
URI = $script:vsCodeSettingsJSON | |
File = -join ($script:vscodeSettingsPath, '\settings.json') | |
} | |
@{ | |
Name = 'VSCode Python Snippets' | |
URI = $script:vsCodePythonSnippetsJSON | |
File = -join ($script:vscodeSnippetsPath, '\python.json') | |
} | |
@{ | |
Name = 'VSCode PowerShell Snippets' | |
URI = $script:vsCodePowerShellSnippetsJSON | |
File = -join ($script:vscodeSnippetsPath, '\powershell.json') | |
} | |
@{ | |
Name = 'Windows Terminal Settings' | |
URI = $script:windowsTerminalSettingsJSON | |
File = -join ($script:windowsTerminalSettingsPath, '\settings.json') | |
} | |
@{ | |
Name = 'oh-my-posh Settings' | |
URI = $script:ohmyposhJSON | |
File = -join ($script:ohmyposhSettings, '\.jake.omp.json') | |
} | |
@{ | |
Name = 'PowerShell profile' | |
URI = $script:psProfile | |
# File = -join ($script:profilePath, '\profile.ps1') | |
File = $profile.CurrentUserAllHosts | |
} | |
) | |
foreach ($setting in $settings) { | |
Start-Sleep -Milliseconds 500 | |
Write-Verbose -Message ('Downloading {0} to {1}' -f $setting.Name, $setting.File) | |
$gistUrl = $null | |
$fileName = $null | |
$gistContent = $null | |
$gistUrl = $setting.URI | |
$fileName = Split-Path $setting.File -leaf | |
# $path = 'C:\rs-pkgs\settings' | |
try { | |
$invokeSplat = @{ | |
Uri = $gistUrl | |
ErrorAction = 'Stop' | |
} | |
$gist = Invoke-RestMethod @invokeSplat | |
$gistContent = $gist.Files.$fileName.Content | |
Write-Verbose -Message ' Download COMPLETED.' | |
} | |
catch { | |
Write-Error $_ | |
continue | |
} | |
try { | |
Write-Verbose -Message ' Writing out content...' | |
$setContentSplat = @{ | |
# Path = "$path\$fileName" | |
Path = $setting.File | |
Value = $gistContent | |
Confirm = $false | |
Force = $true | |
ErrorAction = 'Stop' | |
} | |
Set-Content @setContentSplat | |
Write-Verbose -Message ' Setting applied!' | |
} | |
catch { | |
Write-Error $_ | |
continue | |
} | |
} | |
} #Set-SettingsFiles | |
<# | |
.SYNOPSIS | |
Installs all specified fonts in fonts folder | |
#> | |
function Install-Fonts { | |
[CmdletBinding()] | |
param ( | |
) | |
Write-Verbose -Message 'Starting fonts installation...' | |
$wsFilesPath = -join ($script:tempPath, '\ws_files\ws') | |
$fontPath = -join ($script:tempPath, '\ws_files\ws\Fonts\Fonts') | |
Write-Verbose -Message ' Getting required fonts to install...' | |
. $wsFilesPath\Fonts\PS_Font_Scripts\Add-Font.ps1 -Path $fontPath | |
} #Install-Fonts | |
<# | |
.SYNOPSIS | |
Copies all background images for Windows terminal | |
#> | |
function Set-BackImages { | |
[CmdletBinding()] | |
param ( | |
) | |
Write-Verbose -Message 'Starting Windows Terminal background files copy...' | |
$wsFilesPath = -join ($script:tempPath, '\ws_files\ws\backs') | |
Write-Verbose -Message ' Getting required backgrounds...' | |
$allBackgrounds = Get-ChildItem -Path $wsFilesPath | |
foreach ($background in $allBackgrounds) { | |
$testPath = -join ($script:windowsTerminalBackgroundPath, '\', $background.Name) | |
Write-Verbose -Message (' Evaluating - {0}' -f $background.FullName) | |
if (-not (Test-Path $testPath)) { | |
Write-Verbose -Message ' NOT found. Copying.' | |
Copy-Item -Path $background.FullName -Destination $testPath | |
} | |
else { | |
Write-Verbose -Message ' FOUND. No action taken.' | |
} | |
} | |
} #Set-BackImages | |
function Set-AzurePathVariables { | |
[CmdletBinding()] | |
param ( | |
) | |
$pathsToAdd = @( | |
'C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator' | |
'C:\Program Files (x86)\Microsoft SDKs\Azure\Azcopy' | |
) | |
Write-Verbose -Message 'Backing up curent paths to file...' | |
$fileName = -join ('path_', (Get-Date -format yyyy-MM-ddTHH-mm-ss-ff), '.txt') | |
[System.Environment]::GetEnvironmentVariable('PATH', 'machine') | Out-File "$script:tempPath\$fileName" -Force | |
Write-Verbose -Message 'Evaluating if current paths present...' | |
$paths = ($env:PATH).split(";") | |
foreach ($pathAdd in $pathsToAdd) { | |
$eval = $false | |
foreach ($path in $paths) { | |
if ($path -eq $pathAdd) { | |
$eval = $true | |
Write-Verbose -Message ( '{0} Found!' -f $pathAdd) | |
} | |
} | |
if ($eval -eq $false) { | |
Write-Verbose -Message ( '{0} NOT Found! Adding...' -f $pathAdd) | |
$oldPath = [System.Environment]::GetEnvironmentVariable('PATH', 'machine') | |
$newPath = "$OLDPATH;$pathAdd" | |
[Environment]::SetEnvironmentVariable("PATH", "$NEWPATH", "Machine") | |
} | |
else { | |
Write-Verbose -Message ' No Action taken' | |
} | |
} | |
} #Set-AzurePathVariables | |
#endregion | |
#region main | |
<# | |
.SYNOPSIS | |
Sets up a new workstation for desired development configuration | |
.DESCRIPTION | |
Downloads files, settings, and configurations to set new workstation to desired development setup and config. | |
.EXAMPLE | |
Invoke-WSSetup | |
Configures workstation to base level dev configuration. | |
.EXAMPLE | |
Invoke-WSSetup -Python -AWS -Azure -Fonts | |
Configures workstation to base level dev configuration. Also adds fonts, python, aws, and azure utilities. | |
.PARAMETER Python | |
If specified installs additional Python utilities and settings | |
.PARAMETER AWS | |
If specified installs additional AWS utilities and settings | |
.PARAMETER AWS | |
If specified installs additional AWS CDK utilities for TypeScript CDK | |
.PARAMETER Azure | |
If specified installs additional Azure utilities and settings | |
.PARAMETER Fonts | |
If specified installs downloaded Nerd font packages | |
.NOTES | |
What does this actually do? | |
It downloads a package config zip that contains: | |
- Various Nerd fonts | |
- Background photos for Windows Terminal | |
Installs choco if required | |
Installs base level things like VSCode via choco | |
Downloads configuration from GitHub gists and applies to proper locations: | |
- Configures VSCode with desired configurations | |
- Populates VSCode snippets | |
- Sets oh-my-posh theme configuration | |
- Configures Windows Terminal with desired configurations | |
- Sets PowerShell profile.ps1 | |
Installs base level desired PowerShell modules | |
Install desired VSCode extensions | |
Installs tech specific utilities/configs/extensions based on specified switches | |
#> | |
function Invoke-WSSetup { | |
[CmdletBinding()] | |
param ( | |
[switch]$Software, | |
[switch]$Python, | |
[switch]$AWS, | |
[switch]$AWSCDK, | |
[switch]$Azure, | |
[switch]$Fonts | |
) | |
#Requires -Version 7 | |
#Requires -RunAsAdministrator | |
$ProgressPreference = 'SilentlyContinue' | |
# verify if winget is installed | |
if (-not (Test-WinGet)) { | |
throw 'WinGet not installed. You need to install App Installer from the Microsoft Store' | |
} | |
# remove old versions of Pester | |
Uninstall-Pester | |
# set-up the temp dir if required | |
Write-Verbose -Message 'Verifying temp dir...' | |
if (-not (Test-Path $script:tempPath)) { | |
Write-Verbose -Message ' CREATING temp dir.' | |
New-Item -Path $script:tempPath -ItemType Directory -Force | |
} | |
else { | |
Write-Verbose -Message ' VERIFIED Temp.' | |
} | |
# make sure we have the workstation setup files | |
Get-WSSetupFiles | |
# verify chocolatey is installed | |
if (-not (Test-Choco)) { | |
Install-Choco | |
} | |
# install our base winget packages | |
foreach ($package in $script:wingetCoreTech) { | |
if (-not (Test-WingetInstall -WingetPackage $package)) { | |
Install-WingetPackage -WingetPackage $package | |
} | |
} | |
# install our base choco packages | |
foreach ($package in $script:chocoCoreTech) { | |
if (-not (Test-ChocoInstall -ChocoPackage $package)) { | |
Install-ChocoPackage -ChocoPackage $package | |
} | |
} | |
# temp add vscode path: | |
$env:Path += ";C:\Program Files\Microsoft VS Code\bin" | |
$env:Path += ";$env:LOCALAPPDATA\Programs\Microsoft VS Code\bin" | |
# create snippets path if not created | |
if (-not (Test-Path $script:vscodeSnippetsPath)) { | |
New-Item -Path $script:vscodeSnippetsPath -ItemType Directory -Force | |
} | |
# install our base PowerShell modules | |
Install-BaseModules | |
# install VSCode extensions | |
Install-VSCodeExtension -ExtensionList $script:vscodeExtensions | |
# download and place our settings files | |
Set-SettingsFiles | |
# copy Windows Terminal background images to proper location | |
Set-BackImages | |
# installs fonts if font switch specified | |
if ($fonts) { | |
Install-Fonts | |
} #if_fonts | |
# installs software packages if specified | |
if ($Software) { | |
foreach ($package in $script:wingetSoftwareInstalls) { | |
if (-not (Test-WingetInstall -WingetPackage $package)) { | |
Install-WingetPackage -WingetPackage $package | |
} | |
} | |
foreach ($package in $script:chocoSoftwareInstalls) { | |
if (-not (Test-ChocoInstall -ChocoPackage $package)) { | |
Install-ChocoPackage -ChocoPackage $package | |
} | |
} | |
} #if_software | |
# installs azure resources if azure switch is specified | |
if ($azure) { | |
# install azure winget packages | |
foreach ($package in $script:wingetInstallsAzure) { | |
if (-not (Test-WingetInstall -WingetPackage $package)) { | |
Install-WingetPackage -WingetPackage $package | |
} | |
} | |
# install azure choco packages | |
foreach ($package in $script:chocoInstallsAzure) { | |
if (-not (Test-ChocoInstall -ChocoPackage $package)) { | |
Install-ChocoPackage -ChocoPackage $package | |
} | |
} | |
# install azure Modules | |
Install-HelpfulAzureModules | |
# install azure extensions | |
Install-VSCodeExtension -ExtensionList $script:vscodeExtensionsAzure | |
# set azure path variables | |
Set-AzurePathVariables | |
} #if_azure | |
# installs aws resources if aws switch is specified | |
if ($aws) { | |
# install aws winget packages | |
foreach ($package in $script:wingetInstallsAWS) { | |
if (-not (Test-WingetInstall -WingetPackage $package)) { | |
Install-WingetPackage -WingetPackage $package | |
} | |
} | |
# install aws choco packages | |
foreach ($package in $script:chocoInstallsAWS) { | |
if (-not (Test-ChocoInstall -ChocoPackage $package)) { | |
Install-ChocoPackage -ChocoPackage $package | |
} | |
} | |
# install aws tools installer module | |
Install-Module -Name AWS.Tools.Installer -Scope CurrentUser -Repository PSGallery -Force | |
# install aws modules | |
foreach ($module in $script:awsModules) { | |
Write-Verbose -Message (' {0} evaluating...' -f $module) | |
if (-not (Get-Module $module -ListAvailable)) { | |
Write-Verbose -Message (' Installing {0}' -f $module) | |
Install-AWSToolsModule -Name $module -Scope CurrentUser -Force | |
} | |
else { | |
Write-Verbose -Message (' {0} VERIFIED. NO ACTION TAKEN.' -f $module) | |
} | |
} | |
# special case for AWSLambdaPSCore | |
if (-not (Get-Module 'AWSLambdaPSCore' -ListAvailable)) { | |
Write-Verbose -Message (' Installing {0}' -f $module) | |
Install-Module -Name 'AWSLambdaPSCore' -Scope CurrentUser -Repository PSGallery -Force | |
} | |
else { | |
Write-Verbose -Message (' AWSLambdaPSCore VERIFIED. NO ACTION TAKEN.' -f $module) | |
} | |
# install aws extensions | |
Install-VSCodeExtension -ExtensionList $script:vscodeExtensionsAWS | |
} #if_aws | |
# installs aws cdk resources if awscdk switch is specified | |
if ($awscdk) { | |
# install aws winget packages | |
foreach ($package in $script:wingetAWSCDKTypeScript) { | |
if (-not (Test-WingetInstall -WingetPackage $package)) { | |
Install-WingetPackage -WingetPackage $package | |
} | |
} | |
# install aws cdk useful extensions | |
Install-VSCodeExtension -ExtensionList $script:vscodeExtensionsAWSCDK | |
# temp add vscode path: | |
$env:Path += ";C:\Program Files\nodejs" | |
# Install the TypeScript compiler | |
npm install -g typescript | |
# install aws cdk library | |
npm install aws-cdk-lib | |
# install the aws cdk | |
npm install -g aws-cdk | |
} | |
# installs python resources if python switch is specified | |
if ($python) { | |
# install python extensions | |
Install-VSCodeExtension -ExtensionList $script:vscodeExtensionsPython | |
} #if_python | |
} #Invoke-WSSetup | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment